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; }