• 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:
    ", ++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
    ", 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 }

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

    本文为博主原创文章,未经博主允许不得转载。
  • 相关阅读:
    js简单排序
    js希尔排序
    js直接插入排序
    大数运算
    IOC和AOP的理解 (持续更新)
    频发事件的缓存技巧
    执行上下文深入解析(Execution Context)
    二分
    HDU 3790 最短路径问题 (双重权值)
    浅谈Targan算法
  • 原文地址:https://www.cnblogs.com/alihenaixiao/p/4724973.html
Copyright © 2020-2023  润新知