zoukankan      html  css  js  c++  java
  • hdu-4288 Coder---线段树+离线处理&离散化

    题目链接:

    http://acm.hdu.edu.cn/showproblem.php?pid=4288

    题目大意:

    维护一个有序数列{An},有三种操作:

    1、添加一个元素。

    2、删除一个元素。

    3、求数列中下标%5 = 3的值的和

    解题思路:

    线段树不支持动态的添加,删除操作,所以本题用了离线处理,将所有数字事先离散化,给每个数字存一个位子,然后处理。

    先离线把要用到的数离散化,去重并且排序,这样做添加或删除操作的时候就可以用二分找出下表并在线段树内修改,由于是单点更新,就不用”向下传递“了。

    其实操作和单点更新一样,只是要用一个数组sum[5]记录对应区间内mod5的5种情况的和。所以当添加或删除一个数时都是在sum[1]这里增删,可以想想区间[2,2]是不是只有一个数,那么这个数的下标是1,mod5=1,所以在sum[1]处处理,更新父节点的时候要注意,父亲的左区间的下标与左儿子的下标mod5的情况完全相同,而父亲的右区间和右儿子的下标在左儿子的个数前提上mod5,所以cnt代表区间内有效数的个数。

     1 #include<iostream>
     2 #include<cstdio>
     3 #include<cstring>
     4 #include<algorithm>
     5 #define MID(l, r) (l + (r - l) / 2)
     6 #define lson(o) (o * 2)
     7 #define rson(o) (o * 2 + 1)
     8 using namespace std;
     9 typedef long long ll;
    10 const int INF = 1e9 +7;
    11 const int maxn = 1e6 + 10;
    12 int  h, w, n;
    13 struct node
    14 {
    15     int l, r, tot;//tot表示节点个数
    16     ll sum[5];
    17 }tree[maxn];
    18 void build(int o, int l, int r)
    19 {
    20     tree[o].l = l, tree[o].r = r;
    21     tree[o].tot = 0;
    22     memset(tree[o].sum, 0, sizeof(tree[o].sum));
    23     if(l == r)
    24     {
    25         return;
    26     }
    27     int m = MID(l ,r), lc = lson(o), rc = rson(o);
    28     build(lc, l, m);
    29     build(rc, m + 1, r);
    30 }
    31 //a[p] += v * x
    32 //v表示符号,为1表示add 为-1表示del
    33 int p, v, x;
    34 void update(int o)
    35 {
    36     if(tree[o].l == tree[o].r)
    37     {
    38         tree[o].sum[1] += v * x;
    39         tree[o].tot += v;
    40         return ;
    41     }
    42     int lc = lson(o), rc = rson(o);
    43     if(p <= tree[lc].r)update(lc);
    44     else update(rc);
    45     for(int i = 0; i < 5; i++)
    46         tree[o].sum[i] = tree[lc].sum[i] + tree[rc].sum[((i - tree[lc].tot) % 5 + 5) % 5];
    47     tree[o].tot = tree[lc].tot + tree[rc].tot;
    48 }
    49 
    50 int a[maxn], b[maxn], c[maxn];
    51 int main()
    52 {
    53     while(scanf("%d", &n) != EOF)
    54     {
    55         char s[5];
    56         int tot = 0;
    57         for(int i = 0; i < n; i++)
    58         {
    59             scanf("%s", s);
    60             if(s[0] == 's')
    61                 a[i] = 1;
    62             else
    63             {
    64                 scanf("%d", &b[++tot]);
    65                 if(s[0] == 'a')
    66                     a[i] = 2;
    67                 else a[i] = 3;
    68             }
    69         }
    70         memcpy(c, b, sizeof(c));
    71         sort(b + 1, b + tot + 1);
    72         tot = unique(b + 1, b + tot + 1) - (b + 1);
    73         build(1, 1, tot);
    74         for(int i = 0, j = 0; i < n; i++)
    75         {
    76             if(a[i] == 1)
    77             {
    78                 printf("%lld
    ", tree[1].sum[3]);
    79             }
    80             else
    81             {
    82                 if(a[i] == 2)v = 1;
    83                 else v = -1;
    84                 p = lower_bound(b + 1, b + 1 + tot, c[++j]) - b;
    85                 x = b[p];
    86                 update(1);
    87             }
    88         }
    89     }
    90     return 0;
    91 }
  • 相关阅读:
    sql FLOAT字段使用like查询
    关于sql--时间范围查询重叠
    关于java时间类型比较
    前端-搜索无结果时,怎么把“暂无数据“显示出来?
    v-for动态赋值给不同的下拉框input
    Java的优先队列PriorityQueue详解
    软件体系架构阅读笔记八
    字符数组和字符串之间的转换
    Java快速输入输出
    软件体系架构阅读笔记七
  • 原文地址:https://www.cnblogs.com/fzl194/p/9027211.html
Copyright © 2011-2022 走看看