hdu4288:http://acm.hdu.edu.cn/showproblem.php?pid=4288
题意:有三种类型的操作,(1)."add x",表示往集合里添加数x。(2).“del x”表示将集合中数x删除。(3).“sum”求出从小到大排列的集合中下标模5为3的数的和。集合中的数都是唯一的。
题解:线段树离线操作,一开始没有想到,看了别人的思路才知道用线段树怎么操作。用5个线段树分别维护:下标取模分别为0 1 2 3 4的数的和。对于一棵树的来说,该区间的sum【u】【i】=sum【u<<1】[i],同时,对于幼儿来说,sum【u<<1|1】【i】应该贡献给父亲sum[u][(i+id)%5],id为左子树的个数。
![](https://images.cnblogs.com/OutliningIndicators/ContractedBlock.gif)
1 #include<iostream> 2 #include<cstdio> 3 #include<cstring> 4 #include<algorithm> 5 #define lson u<<1 6 #define rson u<<1|1 7 using namespace std; 8 const int N=100003; 9 long long sum[4*N][5],a[N],idx[N]; 10 int ll[4*N],rr[4*N],num[4*N],top; 11 char op[N][20]; 12 int n; 13 void pushUP(int u){ 14 num[u]=num[lson]+num[rson]; 15 int id=num[lson]; 16 for(int i=0;i<=4;i++){ 17 sum[u][i]=sum[lson][i]; 18 } 19 for(int i=0;i<=4;i++){ 20 sum[u][(i+id)%5]+=sum[rson][i]; 21 } 22 } 23 void build(int l,int r,int u){ 24 ll[u]=l; 25 rr[u]=r; 26 memset(sum[u],0,sizeof(sum[u])); 27 if(l==r){ 28 num[u]=0; 29 return; 30 } 31 int m=(l+r)/2; 32 build(l,m,lson); 33 build(m+1,r,rson); 34 pushUP(u); 35 } 36 void update(int pos,int u,long long val,int fg){ 37 if(ll[u]==rr[u]){ 38 sum[u][1]=val*fg; 39 num[u]=1*fg; 40 return; 41 } 42 int m=(ll[u]+rr[u])/2; 43 if(m>=pos)update(pos,lson,val,fg); 44 else 45 update(pos,rson,val,fg); 46 pushUP(u); 47 } 48 49 int main(){ 50 while(~scanf("%d",&n)){ 51 top=0; 52 for(int i=1;i<=n;i++){ 53 scanf("%s",op[i]); 54 if(op[i][0]=='a'){ 55 scanf("%I64d",&a[i]); 56 idx[++top]=a[i]; 57 } 58 else if(op[i][0]=='d'){ 59 scanf("%I64d",&a[i]); 60 } 61 } 62 sort(idx+1,idx+top+1); 63 int k=unique(idx+1,idx+top+1)-(idx+1); 64 build(1,k,1); 65 for(int i=1;i<=n;i++){ 66 if(op[i][0]=='a'){ 67 int pos=upper_bound(idx+1,idx+k+1,a[i])-(idx+1); 68 update(pos,1,a[i],1); 69 } 70 else if(op[i][0]=='d'){ 71 int pos=upper_bound(idx+1,idx+k+1,a[i])-(idx+1); 72 update(pos,1,0,0); 73 } 74 else{ 75 printf("%I64d ",sum[1][3]); 76 } 77 } 78 } 79 }