HDU 4288 Coder

题意:有三种操作,一种是向集合中加入一个数,第二种操作是在集合中删除一个数,第三种操作时查询集合排序后下表MOD5==3的所有书的加和

思路:看到有大神用vector过了,感觉简直完美,附上传送门(https://blog.csdn.net/Griffin_0/article/details/48000811)

然后就是把所有的数存下来,利用离散化,变成权值线段树,然后一顿操作(反正我是向大家学(chao)习的)

代码:

#include <iostream>
#include <cstdio>
#include <cstring>
#include <cstdlib>
#include <algorithm>
using namespace std;
typedef long long LL;

const int maxn=1e5+7;
int n;
int a[maxn],b[maxn];
char Q[maxn][10];
struct node
{
    LL sum[10];
    int num;
}T[maxn<<2];

void pushup(int rt)
{
    for(int i=0;i<5;i++){
        T[rt].sum[i]=T[rt<<1].sum[i]+T[rt<<1|1].sum[((i-T[rt<<1].num)%5+5)%5];
    }
}


void build(int rt,int l,int r)
{
    T[rt].num=0;
    for(int i=0;i<5;i++){
        T[rt].sum[i]=0;
    }
    if(l==r){
        return ;
    }
    int mid=(l+r)>>1;
    build(rt<<1,l,mid);
    build(rt<<1|1,mid+1,r);
}
void update(int rt,int l,int r,int pos,int val,int op)
{
    op?++T[rt].num:--T[rt].num;
    if(l==pos&&r==pos){
        T[rt].sum[0]=op*val;
        return ;
    }
    int mid=(l+r)>>1;
    if(pos<=mid)update(rt<<1,l,mid,pos,val,op);
    else update(rt<<1|1,mid+1,r,pos,val,op);
    pushup(rt);
}
int main()
{
    while(~scanf("%d",&n)){
        int len=0;
        for(int i=0;i<n;i++){
            scanf("%s",Q[i]);
            if(Q[i][0]!='s'){
                scanf("%d",&a[i]);
                b[len++]=a[i];
            }
        }
        sort(b,b+len);
        len=unique(b,b+len)-b;
        build(1,1,len);
        for(int i=0;i<n;i++){
            if(Q[i][0]=='a'){
                int k=(lower_bound(b,b+len,a[i])-b)+1;
                update(1,1,len,k,a[i],1);
            }
            else if(Q[i][0]=='d'){
                int k=(lower_bound(b,b+len,a[i])-b)+1;
                update(1,1,len,k,a[i],0);
            }
            else{
                printf("%lld\n",T[1].sum[2]);
            }
        }
    }
    return 0;
}

猜你喜欢

转载自www.cnblogs.com/lalalatianlalu/p/9174610.html