题面
Astronomers often examine star maps where stars are represented by points on a plane and each star has Cartesian coordinates. Let the level of a star be an amount of the stars that are not higher and not to the right of the given star. Astronomers want to know the distribution of the levels of the stars.
For example, look at the map shown on the figure above. Level of the star number 5 is equal to 3 (it’s formed by three stars with a numbers 1, 2 and 4). And the levels of the stars numbered by 2 and 4 are 1. At this map there are only one star of the level 0, two stars of the level 1, one star of the level 2, and one star of the level 3.
You are to write a program that will count the amounts of the stars of each level on a given map.
Input
The first line of the input file contains a number of stars N (1<=N<=15000). The following N lines describe coordinates of stars (two integers X and Y per line separated by a space, 0<=X,Y<=32000). There can be only one star at one point of the plane. Stars are listed in ascending order of Y coordinate. Stars with equal Y coordinates are listed in ascending order of X coordinate.
Output
The output should contain N lines, one number per line. The first line contains amount of stars of the level 0, the second does amount of stars of the level 1 and so on, the last line contains amount of stars of the level N-1.
| 输入 | 输出 |
|---|---|
| 5 1 1 5 1 7 1 3 3 5 5 |
1 2 1 1 0 |
Hint:This problem has huge input data,use scanf() instead of cin to read data to avoid time limit exceed.
题意
大河向东流,天上的星星参北斗。给你星星的坐标,数据帮我们处理好了y递增,若y相等,x递增地给出,每个星星都有一个等级就是在它左下方的星星的个数。输入所有星星后,依次输出等级为0到n-1的星星的个数。
什么是树状数组?
首先我们看一个叫树状数组的东西
再将上面的数字改成二进制,你可能就会有点感觉
你可能没有什么感觉,其实我也没感觉。
但是我们可以一个数可以二进制地拆,怎么拆?
我们以7也就是(111)2为例
可以看到(111)2=(111)2+(110)2+(100)2
如下图
你很兴奋,你发现了logn求区间和的方法,此时有人发声前缀和不是O(1)?
是的,我们开始质问他,如果修改某个数,前缀和是不是需要依次修改。
他开始哑口无言,我们顺势拿出logn的树状数组。
然后你突然问我,老哥,这东西怎么修改和求和。
问得好,是一个lowbit,我是说下面这个
#define lowbit(x) ( (x)&(-x) )
lowbit所做的就是取出末位的1所表示的二进制数比如(110)2的lowbit就是(010)2
于是我们就可以用lowbit按照刚才的拆分来求和
那修改呢,你问
我们看回那张图 比如3这里要+2 是不是3以后的全员都要加呢,当然不是
见下图
你惊奇地发现,这不就是一直加lowbit吗,恭喜你参透树状数组。
分析
回到我们的题目,因为数据已经排好序,所以后面的星星不会影响到前面的星星的等级,所以我们只要每次查看新星的等级然后再修改区间和就可以了,看样例
需要注意的是0没有lowbit,所以我们避开0这个东西,即x+1
代码
#include <stdio.h>
#include <string.h>
#define lowbit(x) ( (x)&(-x) )
const int maxn=32005;
int ans[15005],c[maxn];
int sum(int x){
int ans=0;
while(x>0){
ans+=c[x];
x-=lowbit(x);
}
return ans;
}
void add(int x,int val){
while(x<=maxn){
c[x]+=val;
x+=lowbit(x);
}
}
int main(){
int i,n,x,y;
memset(c,0,sizeof(c));
memset(ans,0,sizeof(ans));
scanf("%d",&n);
for(i=0;i<n;i++){
scanf("%d%d",&x,&y);
ans[sum(x+1)]++;
add(x+1,1);
}
for(i=0;i<n;i++) printf("%d\n",ans[i]);
return 0;
}