问题:Stars POJ - 2352
输入点的坐标,记录一个点的相关值,相关值定义为横纵坐标都小于等于这一点的点的个数,最后输出的时候,输出n行,第i行是相关值是i-1的点的个数,输入保证y坐标递增,y相同情况下,x坐标递增
分析:
首先由于输入数据具有递增型,可以不储存数据,来一个分析一个,而且由于y是递增的,所以后加入的点在y方向上就不用再检查是否满足条件了,也就是说我们只用看当前点的x坐标之前(包括x)的点的个数就可以了,这就具有了树状数组的求区间和的需要。每输入一个点,考察它的x坐标,即计算getsum(x),getsum(x)就是这个点的相关值,只需把sum[getsum(x)]++,就是把相关值为getsum(x)的点数++,计算完了之后,再add(x),即x这一坐标的点再加一个,如此往复,最后输出sum[]即可
但是!!!注意x可以从0开始……树状数组是处理不了add(0)的,所以输入x以后要x++
代码:
#include<iostream> #include<cstring> using namespace std; #define MEM(a) memset(a,0,sizeof(a)) #define UP(i,x,y) for(int i=x;i<=y;i++) #define DOWN(i,x,y) for(int i=x;i>=y;i--) const int num=32000; int c[num+10],sum[num+10]; void add(int i){ while(i<=num+10){ c[i]++; i+=i&(-i); } } int getsum(int i){ int s=0; while(i>0){ s+=c[i]; i-=i&(-i); } return s; } int main(){ int n; while(cin>>n){ MEM(c);MEM(sum); int x,y; UP(i,1,n){ scanf("%d %d",&x,&y); x++; sum[getsum(x)]++; add(x); } UP(i,0,n-1){ printf("%d\n",sum[i]); } } return 0; }