Hdu 5372 Segment Game (树状数组)

题目链接:

  Hdu 5372 Segment Game

题目描述:

  有一段区间,对这段区间有两种操作。1:插入操作,第i次插入长度为i的线段,并询问被当前线段完全覆盖的线段数目。

                   2:删除操作,删除第b次插入的线段。

解题思路:

  对于当前新插入线段,只需要统计已插入线段中右端点小于该线段右端点的数目,以及左端点小于该线段做端点的数目,两者相减即可。还有就是离散化问题,sort+unique+map真的是离散化利器(啧啧啧~)。

 1 #include <map>
 2 #include <cstdio>
 3 #include <cstring>
 4 #include <iostream>
 5 #include <algorithm>
 6 using namespace std;
 7 
 8 const int maxn = 200005;
 9 typedef long long LL;
10 struct opera
11 {
12     int a, l, r;
13 }p[maxn];
14 int cl[maxn], cr[maxn], al[maxn], ar[maxn], L[maxn];
15 //树状数组不能从0开始
16 int lowbit (int x)
17 {
18     return x & (-x);
19 }
20 
21 int sum (int x, int a[])
22 {
23     int Sum = 0;
24     while (x > 0)
25     {
26         Sum += a[x];
27         x -= lowbit(x);
28     }
29     return Sum;
30 }
31 
32 void change (int i, int x, int a[], int n)
33 {
34     while (i <= n)
35     {
36         a[i] += x;
37         i += lowbit(i);
38     }
39 }
40 
41 int main ()
42 {
43     int n, m, cnt, t, cas = 0;
44     while (scanf ("%d", &t) != EOF)
45     {
46         memset (cl, 0, sizeof(cl));
47         memset (cr, 0, sizeof(cr));
48         n = m = cnt = 0;
49 
50         for (int i=0; i<t; i++)
51         {
52             scanf ("%d %d", &p[i].a, &p[i].l);
53             if (p[i].a == 0)
54             {
55                 cnt ++;
56                 p[i].r = p[i].l + cnt;
57                 al[n++] = p[i].l;
58                 ar[m++] = p[i].r;
59                 L[cnt] = p[i].l;
60             }
61         }
62 
63         sort (al, al+n);
64         n = unique (al, al+n) - al;
65         sort (ar, ar+m);
66         m = unique (ar, ar+m) - ar;
67         map <int, int> ml, mr;
68         
69         for (int i=0; i<n; i++)
70             ml[al[i]] = i + 1;
71         for (int i=0; i<m; i++)
72             mr[ar[i]] = i + 1;
73 
74         cnt = 0;
75         printf ("Case #%d:\n", ++cas);
76         for (int i=0; i<t; i++)
77         {
78             if (p[i].a)
79             {
80 
81                 int left = ml[L[p[i].l]];
82                 int right = mr[L[p[i].l]+p[i].l];
83                 change (left, -1, cl, n);
84                 change (right, -1, cr, m);
85             }
86             else
87             {
88                 int ansl = sum (ml[p[i].l]-1, cl);
89                 int ansr = sum (mr[p[i].r], cr);
90                 printf ("%d\n", ansr - ansl);
91                 change (ml[p[i].l], 1, cl, n);
92                 change (mr[p[i].r], 1, cr, m);
93             }
94         }
95     }
96     return 0;
97 }

好久没有写过树状数组了,基本忘光光>_<.....,今天算是从新温习了一下(感觉这个代码好渣,改天再改一下)

posted @ 2015-08-12 17:21  罗茜  阅读(188)  评论(0编辑  收藏  举报