原题传送: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 }