AcWing 1265. 数星星 (树状数组)

天空中有一些星星,这些星星都在不同的位置,每个星星有个坐标。

本题采用数学上的平面直角坐标系,即 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 N1 级的星星的数目。

数据范围
1 ≤ N ≤ 15000 , 1≤N≤15000, 1N15000,
0 ≤ x , y ≤ 32000 0≤x,y≤32000 0x,y32000
输入样例:

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;
}
  • 17
    点赞
  • 16
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值