• 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 }
  • 相关阅读:
    微信小程序支付接口之Django后台
    wx.request 请求与django
    ubuntu16.04 安装使用meld及问题
    微信小程序上传单张或多张图片
    ip地址掩码和位数对应关系表、子网掩码、网络地址、主机地址-yellowcong
    公网IP地址就一定是A类地址和B类地址吗?那C类地址就一定是私有地址吗?
    太厉害了,终于有人能把TCP/IP协议讲的明明白白了!
    linux/shell/bash 自动输入密码或文本
    shell case例子
    spring 配置Value常量(不支持到static上)
  • 原文地址:https://www.cnblogs.com/fzl194/p/9027211.html
Copyright © 2020-2023  润新知