![在这里插入图片描述](https://i-blog.csdnimg.cn/blog_migrate/980c643752df23b71d2db70795f47808.png)
![在这里插入图片描述](https://i-blog.csdnimg.cn/blog_migrate/9f01ee70583d504c564f95c0351edf9a.png)
输入样例
5
1 1
5 1
7 1
3 3
5 5
输出样例
1
2
1
1
0
这里使用的是树状数组算法计算,核心函数有三个,因为输入是按照y相同x升序,其他的y升序方法输入,我们可以边输入边处理,(如果不按照这个方法输入,那么可以自己排序这样处理)
因为在处理到这个坐标时比该坐标纵坐标y更大的星星还没有录入系统,那么我们并且比该坐标横坐标x更小的星星已经录入完毕,所以当这个星星录入时,它的等级其实就已经确定了,而且我们可以把已经录入的所有星星的按照x坐标树状数组的方式存储在各个数组,在这个星星录入时再按照树状数组求前缀和的逻辑进行求和,并且不必担心这时我们要求和的数组里有星星不符合题目要求,因为比它纵坐标大的还没计算进去呢,所以肯定都是纵坐标比它小的,我们只需要算存储x下标星星个数数组[0-x]的和即可。
这里x二进制末尾有k个0,lowbit函数返回的是2k,tr[i]数组是指已经录入的星星的横标在 i-lowbit(i)—i 的星星个数之和,level[i]个数是等级为i的星星个数。
最后注意星星的横纵坐标范围,和最后输出时是输出是N行。
使用树状数组x下标不能为0,否则lowbit返回值没有意义。
#include<bits/stdc++.h>
using namespace std;
const int N=35000+5;
int tr[N],level[N];
int n;
int lowbit(int x){
return x&(-x);
}
void add(int x){
for(int i=x;i<N;i+=lowbit(i)) tr[i]++;
}
int sum(int x){
int sum_s=0;
for(int i=x;i>0;i-=lowbit(i)){
sum_s+=tr[i];
}
return sum_s;
}
int main()
{
scanf("%d",&n);
int x,y;
for(int i=0;i<n;i++){
scanf("%d%d",&x,&y);
x++;
level[sum(x)]++;
add(x);
}
for(int i=0;i<n;i++){
printf("%d\n",level[i]);
}
return 0;
}