HDU 4288 Coder [线段树]

  维护一个可以插入删除的有序序列,每次询问序列中位置mod5=3的数的和。

  CodeForces原题,因为时限给的太宽,数据太水,STL可以暴力过。

  用线段树和平衡树都可以做这题,线段树需要先离散化,然后每个区间五个标记分别保存到这个区间左端点的距离mod5=0~4的和,以及一个标记保存这个区间数的个数。合并区间的时候,左儿子因为左端点相同可以直接合并,而右儿子需要推一下,假设左儿子有Num个元素,右儿子本来Mod5=K的点,合并之后到左端点Mod5的值为(num%5+K)%5,所以sum[p][i] = sum[p<<1][i] + sum[p<<1|1][(i-num[p<<1]%5+5) % 5]。

  换了下代码风格,该加空格的地方加上了空格,尽量让自己的代码写的标准一些吧。

 1 #include <string.h>
 2 #include <stdio.h>
 3 #include <algorithm>
 4 #define calm l + r >> 1;
 5 #define lson l, m, p << 1
 6 #define rson m+1, r, p << 1 | 1
 7 #define MAXN 100005
 8 typedef long long LL;
 9 int n,tot,d[MAXN],unq[MAXN],num[MAXN<<2];
10 char s[MAXN][10];
11 LL sum[MAXN<<2][5];
12 void pushup(int p) {
13     for (int i = 0; i < 5; i++)
14         sum[p][i] = sum[p<<1][i] + sum[p<<1|1][(i-num[p<<1]%5+5) % 5];
15 }
16 void update(int x, int v, int o,int l, int r, int p) {
17     num[p] += o ? 1 : -1;
18     if (l == r) {
19         sum[p][0] = o ? v : 0;
20         return;
21     }
22     int m=calm;
23     if(x <= m)update(x, v, o, lson);
24     else update(x, v, o, rson);
25     pushup(p);
26 }
27 int main() {
28     //freopen ("test.in" ,"r", stdin);
29     while (scanf("%d", &n) != EOF) {
30         tot = 0;
31         for (int i = 0; i < n; i++) {
32             scanf("%s", s[i]);
33             if (*s[i] != 's')
34                 scanf("%d", &d[i]), unq[tot++] = d[i];
35         }
36         std::sort(unq, unq + tot);
37         tot = std::unique(unq, unq + tot) - unq;
38         memset(sum, 0, sizeof sum);
39         memset(num, 0, sizeof num);
40         for (int i = 0; i < n; i++) {
41             if (*s[i] == 's') printf("%I64d\n", sum[1][2]);
42             else {
43                 int x = std::lower_bound(unq, unq + tot, d[i]) - unq;
44                 update(x, d[i], *s[i] == 'a' ? 1: 0, 1, tot ,1);
45             }
46         }
47     }
48     return 0;
49 }
posted @ 2012-09-20 06:58  Burn_E  阅读(164)  评论(0编辑  收藏  举报