数星星 Stars

题目传送门
【题目描述】

原题来自:Ural 1028

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

例如,上图中星星 5
是 3 级的(1,2,4 在它左下),星星 2,4 是 1 级的。例图中有 1 个 0 级,2 个 1 级,1 个 2 级,1 个 3

级的星星。

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

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

第一行一个整数 N,表示星星的数目;

接下来 N行给出每颗星星的坐标,坐标用两个整数 x,y表示;

不会有星星重叠。星星按 y坐标增序给出,y 坐标相同的按 x坐标增序给出。
【输出】

N行,每行一个整数,分别是 0 级,1 级,2 级,……,N−1级的星星的数目。
【输入样例】

5
1 1
5 1
7 1
3 3
5 5
【输出样例】

1
2
1
1
0
【提示】

数据范围与提示:

对于全部数据,1≤N≤1.5×104,0≤x,y≤3.2×104

解题思路

对于每个星星按y坐标从小到大排序,相同y坐标按x坐标从小到大排序。输入顺序已排好序,那么只要依次统计星星i之前x坐标小于等于i.x的星星有多少,即是星星i的级别。y坐标没用,显然是一维树状数组应用。
设数组a[x]初始为0,表示在x坐标处星星的个数,则求和a[0] ~ a[x]则为该星星的等级。
有一个地方尤其要注意,树状数组是以1号为起始的,而且只能用1号。x可能为0,为0会时陷入死循环,处理时要将所有的x+1。
还有就是x的范围不能事先确定,在update的时候直接加到x取值范围的最大值,即32001,或者在输入的时候找一个x的最大值。

树状数组(不会的请进)

AC代码

#include<iostream> 
#include<cstdio>
using namespace std;
int n,x,y,s,a[32005],b[32005];
int cx(int x)//查询
{
   
    s=0;//初值
    for(;x;x-=x&(-x))s+=a[x];//累加区间的值
    return s;//返回
}
void update(int x,int y)//更改
{
   
    for(;x<=32001;x+=x&(-x))a[x]+=y;//更改
}
int main()
{
   
    scanf("%d",&n);//用scanf和printf,免得超时
    for(int i=1;i<=n;i++)
	{
   
        scanf("%d%d",&x,&y);
        b[cx(x+1)]++;//累加
        update(x+1,1);//更改
    }
    for(int i=1;i<=n;i++)
     printf("%d\n",b[i-1]);
}

谢谢