-
思路:
已读取的星星的y坐标⩽
对于当前读取的星星,要计算在其左下方的星星个数,
还未读取的星星一定不算在内(要么x>x_{当前},要么y>y_{当前})
故只需在已读取的星星中考虑x_{已读取}\leqslant x_{当前},与y无关(\because当前y是当前最大y)
即求[1,x_{当前}]横坐标范围内有多少个星星\Rightarrow前缀和 -
抽象出操作:
每多读取一颗星星\Rightarrow单点修改
每次求一颗星星的级数\Rightarrow前缀和
故而采用树状数组来进行求解 -
注意:
本题可以使用二维前缀和或一维前缀和计算各星星左下方区域的星星个数,
但由于数据范围过大,只能过部分数据 -
代码:
#include<bits/stdc++.h>
using namespace std;
const int n = 32010;
int tree[n]; // 树状数组
int level[n]; // 等级数组 level[i]记录第i级星星的个数
int lowbit(int x){ return x & -x; }
void add(int x,int y){ for(int i = x;i <= n;i += lowbit(i)) tree[i] += y; }
int sum(int x,int y)
{
int s1 = 0,s2 = 0;
for(int i = y;i > 0;i -= lowbit(i)) s1 += tree[i];
for(int i = x - 1;i > 0;i -= lowbit(i)) s2 += tree[i];
return s1 - s2;
}
int main()
{
int N;
cin >> N;
for(int i = 1;i <= N;i++)
{
int x,y;
cin >> x >> y;
x++; // 确保树状数组下标从1开始
level[sum(1,x)] ++;// 判断当前星星属于哪一级
add(x,1);
}
for(int i = 0;i < N;i++) cout << level[i] << endl;
return 0;
}