题目描述
天空中有一些星星,这些星星都在不同的位置,每个星星有个坐标。 如果一个星星的左下方(包含正左和正下)有k颗星星,就说这颗星星是k级的.
比如,在下面的例图中,星星5是3级的(1,2,4在它左下)。 星星2,4是1级的。例图中有1个0级,2个1级,1个2级,1个3级的星。
【编程任务】
给定星星的位置,输出各级星星的数目。
给定N个点,定义每个点的等级是在该点左下方(含相等)的点的数目,试统计每个等级有多少个点。(1<=N<=15 000,0<=x<=32 000,0<=y<=32 000)
输入
第一行一个整数N(1<=N<=15 000),表示星星的数目。
接下来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
题解
由于这道题的输入刚好是从y由小到大,y相等时x由小到大,所以如果用sum[i]数组表示横坐标不比i大的星星的数量,这个点下方的点都已经被记录过了。然后还要注意的是我们的数组下标是横坐标,所以数组的空间大小是按横坐标的上限来开的。因为横坐标可有存在=0的情况,这时update(0,1)就会无限循环下去,所以将所有的x坐标就增加1来避免这个问题。
#include<iostream>
using namespace std;
int n,sum[32005],c[32005];
int lowbit(int i)
{
return i&(-i);
}
void update(int x,int y)
{
while(x<=32005)
{
c[x]+=y;
x+=lowbit(x);
}
}
int getsum(int a)
{
int ans=0;
for(int i=a;i>0;i-=lowbit(i))
ans+=c[i];
return ans;
}
int main()
{
scanf("%d",&n);
for(int i=1;i<=n;i++)
{
int a,b;
scanf("%d%d",&a,&b);
a++;//避免update(0,1)的死循环
sum[getsum(a)]++;
update(a,1);
}
for(int i=0;i<n;i++)
printf("%d\n",sum[i]);
return 0;
}