http://codeforces.com/problemset/problem/85/D
题意:
给你N(0<N<1e5)次操作,每次操作有3种方式,
1.向集合里加一个数a(0<a<1e9)(增加数a之前的集合一定不存在a)
2.向集合里删一个数a(0<a<1e9)(删除数a之前的集合一定存在a)
3.将下标i%5==3的数相加,计算总和并相加.
分析:
先离散,然后线段树,sum[i]用来标识前i项有几个数,ans[rt][i]表示以rt为根的子树中第i大数的和
// File Name: d.cpp // Author: Zlbing // Created Time: 2013/7/18 20:22:40 #include<iostream> #include<string> #include<algorithm> #include<cstdlib> #include<cstdio> #include<set> #include<map> #include<vector> #include<cstring> #include<stack> #include<cmath> #include<queue> using namespace std; #define CL(x,v); memset(x,v,sizeof(x)); #define INF 0x3f3f3f3f #define LL long long #define REP(i,r,n) for(int i=r;i<=n;i++) #define RREP(i,n,r) for(int i=n;i>=r;i--) #define lson l,m,rt<<1 #define rson m+1,r,rt<<1|1 const int MAXN=1e5+1000; char str[MAXN][10]; int d[MAXN]; int hash[MAXN]; int tot; int sum[MAXN<<2]; LL ans[MAXN<<2][10]; int flag; void pushup(int rt) { for(int i=0;i<5;i++) { ans[rt][i]=ans[rt<<1][i]+ans[rt<<1|1][(i-sum[rt<<1]%5+5)%5]; } } void update(int pos,int l,int r,int rt) { sum[rt]+=flag*2-1; if(l==r) { ans[rt][0]=hash[pos]*flag; return; } int m=(l+r)>>1; if(pos<=m)update(pos,lson); else update(pos,rson); pushup(rt); } int main() { int n; while(~scanf("%d",&n)) { tot=0; REP(i,1,n) { scanf("%s",str[i]); if(str[i][0]=='a'||str[i][0]=='d') { scanf("%d",&d[i]); hash[tot++]=d[i]; } } sort(hash,hash+tot); tot=unique(hash,hash+tot)-hash; CL(ans,0); CL(sum,0); REP(i,1,n) { if(str[i][0]=='a') { flag=1; int pos=lower_bound(hash,hash+tot,d[i])-hash; update(pos,1,tot,1); } else if(str[i][0]=='d') { flag=0; int pos=lower_bound(hash,hash+tot,d[i])-hash; update(pos,1,tot,1); } else { printf("%I64d\n",ans[1][2]); } } } return 0; }