天空中有一些星星,这些星星都在不同的位置,每个星星有个坐标。
本题采用数学上的平面直角坐标系,即 x x x 轴向右为正方向, y y y 轴向上为正方向。
如果一个星星的左下方(包含正左和正下)有
k
k
k 颗星星,就说这颗星星是
k
k
k 级的。
例如,上图中星星
5
5
5 是
3
3
3 级的(
1
,
2
,
4
1,2,4
1,2,4 在它左下),星星
2
,
4
2,4
2,4 是
1
1
1 级的。
例图中有 1 1 1 个 0 0 0 级, 2 2 2 个 1 1 1 级, 1 1 1 个 2 2 2 级, 1 1 1 个 3 3 3 级的星星。
给定星星的位置,输出各级星星的数目。
换句话说,给定 N N N 个点,定义每个点的等级是在该点左下方(含正左、正下)的点的数目,试统计每个等级有多少个点。
输入格式
第一行一个整数
N
N
N,表示星星的数目;
接下来 N N N 行给出每颗星星的坐标,坐标用两个整数 x , y x,y x,y 表示;
不会有星星重叠。星星按 y y y 坐标增序给出, y y y 坐标相同的按 x x x 坐标增序给出。
输出格式
N
N
N 行,每行一个整数,分别是
0
0
0 级,
1
1
1 级,
2
2
2 级,……,
N
−
1
N−1
N−1 级的星星的数目。
数据范围
1
≤
N
≤
15000
,
1≤N≤15000,
1≤N≤15000,
0
≤
x
,
y
≤
32000
0≤x,y≤32000
0≤x,y≤32000
输入样例:
5
1 1
5 1
7 1
3 3
5 5
输出样例:
1
2
1
1
0
本题实现限制 200 m s 200ms 200ms,只能用线段树或者树状数组,平衡树来做。
这题能够使用树状数组的一个条件是,题目给出坐标的顺序是按照 y y y 坐标递增给出的。
所以就可以一步步的读入坐标,这时候就已经保证了扫的时候就只能扫到比当前 y y y 轴低的点,之后再通过树状数组扫当前 x x x 前面的点,就同时满足了去扫 x x x 小于等于当前点并且 y y y 小于等于当前点的点的个数。
#include<iostream>
using namespace std;
const int N = 15010;
const int M = 32010;
int tr[M];
int n;
int a[N];
int ans[N];
int lowbit(int x) { return x & -x; }
void add(int x, int c) {
for (int i = x; i <= M; i += lowbit(i))tr[i] += c;
}
int sum(int x) {
int res = 0;
for (int i = x; i; i -= lowbit(i))res += tr[i];
return res;
}
int main() {
cin >> n;
int x, y;
for (int i = 1; i <= n; i++) {
cin >> x >> y;
x++;//让x自增,因为题目给出的x是从0开始的,树状数组中下标是从1开始的
ans[sum(x)]++;
add(x, 1);
}
for (int i = 0; i <= n - 1; i++)cout << ans[i] << endl;
return 0;
}