1 #include <iostream> 2 #include <cstdio> 3 #include <cstring> 4 #include <cmath> 5 #include <algorithm> 6 7 using namespace std; 8 9 #define mid (l+r)>>1 10 #define ls rt<<1 11 #define rs rt<<1|1 12 #define lson l,m,rt<<1 13 #define rson m+1,r,rt<<1|1 14 15 #define MAXN 100010 16 int sum[MAXN<<2]; //区间的元素个数 17 __int64 ans[MAXN<<2][5];//分别表示mod5 18 int key[MAXN];//离散化用 19 int x[MAXN]; 20 21 char op[MAXN][10]; 22 23 void pushup(int rt) 24 { 25 for(int i=0;i<5;i++) 26 { 27 ans[rt][i]=ans[ls][i]+ans[rs][(i-sum[ls]%5+5)%5]; 28 } 29 } 30 31 void build(int l,int r,int rt) 32 { 33 sum[rt]=0; 34 memset(ans[rt],0,sizeof(ans[rt])); 35 if(l==r) 36 return; 37 int m = mid; 38 build(lson); 39 build(rson); 40 } 41 42 int flag;//判断用 43 void update(int p,int l,int r,int rt) 44 { 45 sum[rt]+=2*flag-1; 46 if (l==r) 47 { 48 ans[rt][1]=flag*key[p];//叶子节点的值mod5肯定为1 49 return ; 50 } 51 int m=mid; 52 if (p<= m) 53 update(p,lson); 54 else 55 update(p,rson); 56 pushup(rt); 57 } 58 59 int main() 60 { 61 int n,tot=0; 62 while(scanf("%d",&n) != EOF) 63 { 64 tot=0; 65 for(int i=0;i<n;i++) 66 { 67 scanf("%s",op[i]); 68 if(op[i][0]=='a' || op[i][0]=='d') 69 { 70 scanf("%d",&x[i]); 71 key[tot++]=x[i]; 72 } 73 } 74 sort(key,key+tot); 75 tot = unique(key,key+tot) - key; 76 build(1,tot,1); 77 for(int i=0;i<n;i++) 78 { 79 int pos = lower_bound(key,key+tot,x[i]) - key; 80 if(op[i][0] == 's') 81 printf("%I64d\n",ans[1][3]); 82 else 83 { 84 if(op[i][0]=='a') 85 flag=1; 86 else 87 flag=0; 88 update(pos,1,tot,1); 89 } 90 } 91 } 92 return 0; 93 }
线段树 + 离散化 :
这题是codeforce上的原题。。。o(︶︿︶)o 唉。
用ans[][5]分别表示区间内mod5==i的五种情况的和。比如ans[][2]==4,表示这个区间内下表mod5==2的值的和为4.
假如我们 求 i == 3 时 (表示 %5 == 3)
对于左子树我们直接求就可以 ,但是对于右子树,我们要知道 在 i== 3 的 情况下 ,右子树的元素的下标应该是 %5 == 几?
ans[rt][i]=ans[ls][i]+ans[rs][(i-sum[ls]%5+5)%5];