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("
");
72     }
73     return 0;
74 }
WA Code
原文地址:https://www.cnblogs.com/ACMERY/p/4768217.html