题意:天文学家经常检测星星地图,星星以点的坐标显示在平面上,并且每个星星都有它的笛卡尔坐标。一个星星的等级由小于等于它的x坐标和小于等于它的y坐标的星星数量决定。天文学家想知道每个等级的星星数量。

分析:我们可以先排序一维,把所有星星按照x坐标排序,再用树状数组维护另一维,从左到右插入每个星星的y坐标,并且查询小于当前星星的y坐标的星星数量,这样就可以满足比当前星星x坐标小并且y坐标小的星星数量。注意这道题目的y坐标可能存在0,而树状数组的坐标是从1开始的,所以我们要读入的时候++。

#include <iostream>
#include <cstdio>
#include <cstring>
#include <string>
#include <algorithm>

using namespace std;
const int N = 330005;
struct Node
{
	int x, y;
	bool operator<(const Node& rhs)const
	{
		if (x == rhs.x)
			return y < rhs.y;
		return x < rhs.x;
	}
}a[N];

int c[N], res[N];
//星星的数量
int n;

int lowbit(int x)
{
	return x & (-x);
}

void add(int x, int val)
{
	for (int i = x; i < N; i += lowbit(i))
		c[i] += val;
}

int query(int x)
{
	int res = 0;
	for (int i = x; i; i -= lowbit(i))
		res += c[i];
	return res;
}

int main()
{
	while (scanf("%d", &n) != EOF)
	{
		//scanf("%d", &n);

		for (int i = 1; i <= n; ++i) scanf("%d", &a[i].x), scanf("%d", &a[i].y), ++a[i].y;

		sort(a + 1, a + n + 1);

		int cnt = 0;
		for (int i = 1; i <= n; ++i)
		{
			//查询<=a[i].y的点个数
			cnt = query(a[i].y);
			++res[cnt];
			add(a[i].y, 1);
		}

		for (int i = 0; i < n; ++i)
			printf("%d\n", res[i]);
		memset(res, 0, sizeof res);
		memset(c, 0, sizeof c);
	}

	

	return 0;
}