hdu 4288 Coder (线段树+离线)

题意:

刚开始有一个空集合。有三种操作:

1.往集合中加入一个集合中不存在的数 x

2.从集合中删除一个已经存在的数 x

3.计算集合的digest sum并输出。       digest sum求法:将集合中所有数从小到大排序,得到a1<a2<...<an。 digest sum = sum(ai) where i mod 5 = 3

数据范围:

N ( 1 <= N <= 105 )

1 <= x <= 109.

For any “add x” it is guaranteed that x is not currently in the set just before this operation.
For any “del x” it is guaranteed that x must currently be in the set just before this operation.

思路:

先将所有增加过的,删除过的数存下来,去重,搞成线段树。

每个结点(区间)里有两个东西,一个是 cnt,记录该区间的在集合中的元素的个数。一个是sum[i] , sum[i]:该区间序号%5等于i的存在于集合中的元素的总和。

插入和删除时维护即可。

代码:

int const maxn=1e5+5;

struct node{
    int cnt;
    ll sum[5];
}tree[maxn<<2];

int n,tot;
int q[maxn],a[maxn];
char ope[maxn][15];

void build(int l,int r,int rt){
    tree[rt].cnt=0;
    memset(tree[rt].sum,0,sizeof(tree[rt].sum));
    if(l==r) return;
    int m=(l+r)>>1;
    build(lson);
    build(rson);
}

void pushUp(int rt){
    rep(i,0,4)
        tree[rt].sum[i]=tree[rt<<1].sum[i]+tree[rt<<1|1].sum[((5-tree[rt<<1].cnt%5)%5+i)%5];
}
void update(int k,int pos,int num,int l,int r,int rt){
    tree[rt].cnt+=k;
    if(l==r){
        tree[rt].sum[0]+=(k*num);
        return;
    }
    int m=(l+r)>>1;
    if(pos<=m)
        update(k,pos,num,lson);
    else
        update(k,pos,num,rson);
    pushUp(rt);
}

int main(){
    //freopen("test.in","r", stdin);
    while(scanf("%d",&n)!=EOF){
        tot=0;
        rep(i,1,n){
            scanf("%s",ope[i]);
            if(ope[i][0]!='s'){
                scanf("%d",&q[i]);
                a[tot++]=q[i];
            }
        }
        sort(a,a+tot);
        tot=unique(a,a+tot)-a;
        if(tot==0)
            memset(tree[1].sum,0,sizeof(tree[1].sum));
        else
            build(1,tot,1);
        rep(i,1,n){
            int pos=lower_bound(a,a+tot,q[i])-a+1;
            if(ope[i][0]=='a'){
                update(1,pos,q[i],1,tot,1);
                continue;
            }
            if(ope[i][0]=='d'){
                update(-1,pos,q[i],1,tot,1);
                continue;
            }
            printf("%I64d
",tree[1].sum[2]);
        }
    }
    //fclose(stdin);
}
原文地址:https://www.cnblogs.com/fish7/p/4050006.html