#sZSZybttg040102. 1536:【例 2】数星星 Stars

1536:【例 2】数星星 Stars

好的,我将这道题整理为清晰的题面格式,并补充样例解释、数据范围与时空限制:


题目描述

原题来自:Ural 1028

天空中有一些星星,这些星星都在不同的位置,每个星星有个坐标。如果一个星星的左下方(包含正左和正下)有 kk 颗星星,就说这颗星星是 kk 级的。

例如,下图中星星 5533 级的(星星 1,2,41,2,4 在它左下),星星 2,42,411 级的。例图中有 1100 级,2211 级,1122 级,1133 级的星星。

给定星星的位置,输出各级星星的数目。

一句话题意:给定 nn 个点,定义每个点的等级是在该点左下方(含正左、正下)的点的数目,试统计每个等级有多少个点。


输入格式

  • 第一行一个整数 NN,表示星星的数目;
  • 接下来 NN 行,每行两个整数 x,yx, y,表示星星的坐标。

输入保证:

  • 不会有星星重叠;
  • 星星按 yy 坐标增序给出,yy 坐标相同的按 xx 坐标增序给出。

输出格式

输出 NN 行,每行一个整数,分别是 00 级,11 级,22 级,……,N1N-1 级的星星的数目。


样例

样例输入

5
1 1
5 1
7 1
3 3
5 5

样例输出

1
2
1
1
0

样例说明

星星坐标:

  1. (1,1)
  2. (5,1)
  3. (7,1)
  4. (3,3)
  5. (5,5)

等级计算:

  • 星星1:左下方没有星星,等级0;
  • 星星2:左下方有星星1,等级1;
  • 星星3:左下方有星星1,2,等级2;
  • 星星4:左下方有星星1,等级1;
  • 星星5:左下方有星星1,2,4,等级3。

等级统计:

  • 等级0:1个
  • 等级1:2个
  • 等级2:1个
  • 等级3:1个
  • 等级4:0个

因此输出:

1
2
1
1
0

数据范围

对于全部数据:

  • 1N1.5×1041 \le N \le 1.5\times 10^4
  • 0x,y3.2×1040 \le x, y \le 3.2\times 10^4

时空限制

  • 时间:256 ms256 \text{ ms}
  • 内存:65536 KB65536 \text{ KB}(64 MB)

提示
此题是 树状数组(Fenwick Tree) 的经典应用。

关键点
由于星星按 yy 坐标递增的顺序给出(yy 相同按 xx 递增),所以当读到第 ii 颗星星时,所有 yy 坐标小于它的星星已经全部给出(且 yy 坐标相等但 xx 坐标小于它的也给出了)。因此,对于当前星星 (xi,yi)(x_i, y_i),它的等级就是之前所有 xx 坐标 xi\le x_i 的星星数量。

问题转化
实时维护一个数组 cnt[x]cnt[x],表示当前 xx 坐标出现的星星数,然后查询前缀和 sum(xi)=k=0xicnt[k]sum(x_i) = \sum_{k=0}^{x_i} cnt[k] 即为该星星的等级。
因为 xx 坐标范围是 [0,32000][0, 32000],我们需要支持:

  • 单点更新:cnt[x]cnt[x]+1cnt[x] \gets cnt[x] + 1
  • 前缀和查询:sum(x)sum(x)

这正好是树状数组的典型操作。

步骤

  1. 初始化一个长度为 maxX+1maxX+1maxX=32000maxX = 32000)的树状数组,全部为 00
  2. 对于每颗星星 (x,y)(x, y)
    • 查询 level=sum(x)level = sum(x)(即当前星星的等级);
    • ans[level]ans[level]11
    • 执行更新 add(x,1)add(x, 1)
  3. 最后依次输出 ans[0N1]ans[0 \dots N-1]

复杂度:O(NlogX)O(N \log X),其中 X=32000X = 32000,可以很快。

注意

  • 因为坐标从 00 开始,树状数组下标通常从 11 开始,可以将 xx11 处理;
  • 输出 NN 行,即使有些等级没有星星也要输出 00