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\n", 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 }
越努力,越幸运