HDU4288 Coder

  原题传送:http://acm.hdu.edu.cn/showproblem.php?pid=4288

  线段树。

  技巧有一下几个:

    1. 先把数据全部输入完毕后再统一查询,进行排序预处理方便计算出元素位置(线段树的堆底是静态的);

    2. 每个区间节点保存mod 5 = 0...4这5个值;

    3. 合并区间时,左孩子起点就是当前区间起点,可以直接合并,但是相应的右孩子节点变为(k + 5 - num(lson) % 5 ) % 5 (k为合并前mod5的点,num(lson)为左孩子的点数)。

线段树
 1 #include <stdio.h>
 2 #include <string.h>
 3 #include <algorithm>
 4 #include <iostream>
 5 #define lson (cur << 1)
 6 #define rson (cur << 1 | 1)
 7 #define N 100005
 8 #define LL long long
 9 int v[N], d[N], tot, num[N << 2];
10 char cmd[N][5];
11 
12 LL tree[N << 2][5];
13 
14 void push_up(int cur)
15 {
16     for(int i = 0; i < 5; i ++)
17        tree[cur][i] = tree[lson][i] + tree[rson][(i + (5 - num[lson] % 5)) % 5];
18 }
19 
20 void update(int cur, int l, int r, int loc, LL k, bool flag)
21 {
22     num[cur] += flag ? 1 : -1;
23     if(l == r)
24     {
25         tree[cur][0] = (flag ? k : 0);
26         return ;
27     } 
28     int mid = (l + r) >> 1;
29     if(loc <= mid)
30         update(lson, l, mid, loc, k, flag);
31     else
32         update(rson, mid + 1, r, loc, k, flag);
33     push_up(cur);
34 }
35 
36 int main()
37 {
38     int i, n;
39     while(scanf("%d", &n) != EOF)
40     {
41         for(tot = i = 0; i < n; i ++)
42         {
43             scanf("%s", cmd[i]);
44             if(cmd[i][0] != 's')
45             {
46                 scanf("%I64d", &d[i]);
47                 v[tot ++] = d[i];
48             }
49         }
50         std::sort(v, v + tot);
51         memset(tree, 0, sizeof tree);
52         memset(num, 0, sizeof num);
53         for(i = 0; i < n; i++)
54         {
55             if(cmd[i][0] == 's')
56                 printf("%I64d\n", tree[1][2]);
57             else
58             {
59                 int loc = std::lower_bound(v, v + tot, d[i]) - v;
60                 update(1, 1, tot, loc, d[i], cmd[i][0] == 'a' ? 1 : 0);
61             }
62         }
63     }
64     return 0;
65 }

  

原文地址:https://www.cnblogs.com/huangfeihome/p/2695023.html