hdu 4288 Coder (线段树,区间部分更新)

http://acm.hdu.edu.cn/showproblem.php?pid=4288

题意:

给出三种操作add x 向集合里添加x(这里保证集合中不存在该元素), del x删除集合里的x(这里保证集合里面不存在x),

sum:

然后给出N个操作,输出每次的sum;

思路:

才开始看到这题就想到了上次那个维护区间(i-a)%k == 0的题目区间部分更新的题目,每个线段树上的节点添加记录该区间内模k余(0到k-1)的值,可是这里是求整个区间,而且一旦删除一个值它们原来满足模k的余数就会发生改变。直接就晕了。。。看了下解题报告原来和上次的题目是类似的,我们还是记录当前区间模5余(0到4)的值,只是稍微进行一下区间合并即可,解题的关键就在于这里的区间合并。当向上更新的时候当前节点的左子树模5余数不变,只要加上就好,而对于右子树由于在该区间的前边又添加len[rt<<1]这些长度的值,所以原来他们模5的余数对于整体的父亲节点来说已经改变了我们只要右子树模5等于i的现在对应于父亲节点为模5等与(len[rt<<1] + i )%5.然后合并完毕了。。

离散化+离线处理 +区间合并

View Code
#include <iostream>
#include <cstdio>
#include <cstring>
#include <algorithm>
#include <cmath>
#include <queue>
#include <stack>
#include <set>
#include <map>
#include <string>

#define CL(a,num) memset((a),(num),sizeof(a))
#define iabs(x)  ((x) > 0 ? (x) : -(x))
#define Min(a,b) (a) > (b)? (b):(a)
#define Max(a,b) (a) > (b)? (a):(b)

#define ll __int64
#define inf 0x7f7f7f7f
#define MOD 100000007
#define lc l,m,rt<<1
#define rc m + 1,r,rt<<1|1
#define pi acos(-1.0)
#define test puts("<------------------->")
#define maxn 10000007
#define M 100007
#define N 100007
using namespace std;
//freopen("din.txt","r",stdin);

ll Mod[N<<2][5];
int len[N<<2];
int val[N],a[N];
char op[N][5];

void pushup(int rt){
    int i;
    len[rt] = len[rt<<1] + len[rt<<1|1];
    //关键理解合并
    for (i = 0; i < 5; ++i) Mod[rt][i] = Mod[rt<<1][i];
    int Lx = len[rt<<1];
    for (i = 0; i < 5; ++i) Mod[rt][(Lx + i)%5] += Mod[rt<<1|1][i];
}
void build(int l,int r,int rt){
    for (int i = 0; i < 5; ++i) Mod[rt][i] = 0;
    len[rt] = 0;
    if (l == r) return ;
    int m = (l + r)>>1;
    build(lc);
    build(rc);
}
void update(int pos,int sc,int l,int r,int rt){
    if (l == r){
        len[rt] += sc;
        Mod[rt][1] += sc*a[l];//对于一个叶子节点来说区间是[1,1]所以模5等于1
        return ;
    }
    int m = (l + r)>>1;
    if (pos <= m) update(pos,sc,lc);
    else update(pos,sc,rc);
    pushup(rt);
}
int bSearch(int L,int R,int v){
    int l = L;
    int r = R;
    while (l <= r){
        int m = (l + r)>>1;
        if (a[m] == v) return m;
        else if (v < a[m]) r = m - 1;
        else l = m + 1;
    }
    return -1;
}
int main(){
    //freopen("din.txt","r",stdin);
    int i,n;
    while (~scanf("%d",&n)){
        int ct = 0;
        for (i = 0; i < n; ++i){
            scanf("%s",op[i]);
            if (op[i][0] != 's'){
                scanf("%d",&val[i]);
                a[++ct] = val[i];
            }
        }
        //离散化
        sort(a + 1,a + 1 + ct);
        int nn = 1;
        for (i = 2; i <= ct; ++i){
            if (a[i] != a[i - 1]) a[++nn] = a[i];
        }
        //离线处理
        build(1,nn,1);
        for (i = 0; i < n; ++i){
            if (op[i][0] == 'a') update(bSearch(1,nn,val[i]),1,1,nn,1);
            else if (op[i][0] == 'd') update(bSearch(1,nn,val[i]),-1,1,nn,1);
            else printf("%I64d\n",Mod[1][3]);
        }
    }
    return 0;
}

 

 

 

posted @ 2012-09-17 21:14  E_star  阅读(473)  评论(1编辑  收藏  举报