最近在学线段树,总感觉线段树的题目比较灵活,,用线段树的题目很容易和其他数据结构的题目区分开来。
URL:POJ:2352
这题主要在输入方面对做题很有优势,首先按y升序,y相同,按x升序。所以在考虑区间时,就可以只考虑x就可以。
这题如果用树状数组做的话,更容易,因为要统计区间内的星星数目。
废话不多说,上代码:
#include <stdio.h> #include <string.h> #define MAX 100000 #define MAX_POINT 32005 struct SegTree{ int left,right; int count; }st[MAX]; int level[MAX>>2]; //储存level的 void creatTree(int left , int right , int pos) { st[pos].left = left ; st[pos].right = right ; st[pos].count = 0 ; if(left == right) { return ; } int mid = (left + right)>>1; creatTree(left,mid,pos<<1); creatTree(mid+1,right,pos<<1|1); } void update(int x , int pos) //更新区间,为什么只更新一个点呢,,因为如果更新一个区间的话,就会重复统计。只更新点所在的区间,方便统计 { ++st[pos].count ; if(st[pos].left == st[pos].right && st[pos].right == x) { return ; } int mid = (st[pos].left + st[pos].right)>>1; if(x > mid) { update(x,pos<<1|1); } else { update(x,pos<<1); } } int count(int left , int right , int pos) //统计相同等级的星星个数 { int sum = 0 ; if(st[pos].left == left && st[pos].right == right) { return st[pos].count ; } int mid = (st[pos].left + st[pos].right)>>1; if(left > mid) { sum += count(left,right,pos<<1|1); } else if(right <= mid) { sum += count(left,right,pos<<1); } else { sum += count(left,mid,pos<<1); sum += count(mid+1,right,pos<<1|1); } return sum ; } int main() { int n ; while(scanf("%d",&n) != EOF) { int x , y; creatTree(0,MAX_POINT,1); memset(level,0,sizeof(int)*(MAX>>2)); for(int i = 0 ; i < n ; ++i) { scanf("%d%d",&x,&y); level[count(0,x,1)]++; //先找星星,再更新线段树 update(x,1); } for(int i = 0 ; i < n ; ++i) { printf("%d\n",level[i]); } } return 0; }