POJ 2481-树状数组
题意:给定几个区间,判断该区间是其余区间的真子集个数。
分析:真子集即寻找x,y满足a(小于或等于x),b(大于或等于y)的区间。跟star-POJ2352很类似。
转化:star那个题目是x,y都是从小到大排序,然后直接求y序列前边比y小的数字个数。这个就需要x从小到大排,y从大到小排,然后求y序列的前边比当前更大的y值。其实也是序号 - 前边比当前更小的y值。
1 #include<cstdio> 2 #include<iostream> 3 #include<cstring> 4 #include<algorithm> 5 using namespace std; 6 const int MAXN = 100010; 7 int c[MAXN]; 8 int ans[MAXN]; 9 int n; 10 struct S 11 { 12 int x,y,pos; 13 bool operator < (const S &a) const 14 { 15 if(x == a.x) 16 return y > a.y; 17 else 18 return x < a.x; 19 } 20 } a[MAXN]; 21 int lowbit(int x) 22 { 23 return x&(-x); 24 } 25 int getsum(int i) 26 { 27 int s=0; 28 while(i>0) 29 { 30 s += c[i]; 31 i -= lowbit(i); 32 } 33 return s; 34 } 35 void add(int li, int val) 36 { 37 while(li<=MAXN) 38 { 39 c[li] += val; 40 li += lowbit(li); 41 } 42 } 43 int main() 44 { 45 ///找前边有几个x,y都比当前小的 46 while(scanf("%d",&n),n) 47 { 48 memset(c,0,sizeof(c)); 49 memset(ans,0,sizeof(ans)); 50 for(int j=0; j<n; j++) 51 { 52 scanf("%d%d",&a[j].x,&a[j].y); 53 a[j].x++; 54 a[j].y++; 55 a[j].pos = j ; 56 } 57 sort(a,a+n); 58 ans[a[0].pos] = getsum(a[0].x); //ans[]代表各点的sum() 59 add(a[0].x, 1); 60 for(int i = 1; i < n; i++) 61 { 62 if(a[i].x == a[i-1].x && a[i].y == a[i-1].y) //若两区间相等 63 ans[a[i].pos] = ans[a[i-1].pos]; //该值等于上一个的值 64 else 65 ans[a[i].pos] = getsum(a[i].x); 66 add(a[i].x, 1); //更新该点x值 67 } 68 printf("%d", ans[0]); 69 for(int i = 1; i < n; i++) 70 printf(" %d", ans[i]); 71 printf("\n"); 72 } 73 return 0; 74 }
人生就像心电图,想要一帆风顺,除非game-over