Codeforces Problem - 652D - Nested Segments
D. Nested Segments
time limit per test2 seconds
memory limit per test256 megabytes
inputstandard input
outputstandard output
You are given n segments on a line. There are no ends of some segments that coincide. For each segment find the number of segments it contains.
Input
The first line contains a single integer n (1?≤?n?≤?2·105) — the number of segments on a line.
Each of the next n lines contains two integers li and ri (?-?109?≤?li?<?ri?≤?109) — the coordinates of the left and the right ends of the i-th segment. It is guaranteed that there are no ends of some segments that coincide.
Output
Print n lines. The j-th of them should contain the only integer aj — the number of segments contained in the j-th segment.
Examples
input
4
1 8
2 3
4 7
5 6
output
3
0
1
0
input
3
3 4
1 5
2 6
output
0
1
1
给出\(n\)条线段,问每条线段包含有多少条线段。保证没有两条线段有相同的终点。
树状数组+离散化
大佬们都说跟POJ - 2481 Cows一样,就是多了个离散化,然而作为蒟蒻的我想了好久都没想明白,果然还是要看大佬的代码。离散不会orz.....
因为右端点都是不同的,所以先按线段右端点从小到大排序,然后从小到大赋值1到n,这样数据范围就变小了。我们只要开一个2e5的数组就可以存储所有点了。
然后按照线段的左端点从大到小排序,如果左端点一样,就按照右端点从小到大排序。因为前面线段的左端点大于等于当前的左端点,所以只要判断这些线段里有多少右端点是小于当前线段的右端点的就可以了。我们开一个2e5的树状数组来存储有多少个点在当前这个点前面(即有多少条线段的右端点是小于这个点的),然后每次把当前线段的右端点加入进去。
#include
#include
#include
using namespace std;
struct point{
int x,y,num;
};
bool cmp(point i,point j)
{
return i.yj.x;
else return i.y 0)
{
sum+=d[x];
x-=lowbit(x);
}
return sum;
}
void update(int x)
{
while (x <=n)
{
d[x]++;
x+=lowbit(x);
}
}
int main()
{
scanf("%d",&n);
for (int i = 1;i<=n;i++)
{
scanf("%d%d",&a[i].x,&a[i].y);
a[i].num = i;
}
sort(a+1,a+n+1,cmp);
for (int i = 1;i<=n;i++) a[i].y = i;//离散化
sort(a+1,a+n+1,cmp1);
for (int i = 1;i<=n;i++)
{
c[a[i].num] = query(a[i].y);//查询区间
update(a[i].y);//把当前线段的终点更新进d数组
}
for (int i = 1;i<=n;i++) printf("%d\n",c[i]);
}
蒟蒻的线段树/树状数组学习之旅orz