题目:http://codeforces.com/problemset/problem/85/D
因为题目有3秒,可以用vector暴力。还有可以线段树搞。
用线段树的话,统计两个东西,1个统计sum[id] 就是统计 id这一段内所包含的数的个数。 2 ans[id][x] 统计 id这一段内 下标除5余数为x 的所有数和。
1比较容易计算。当插入数据这段区间+1,当删除数据这段区间-1。 关键是求2,容易知道当某数据插入x到树底时,肯定是ans[id][0]= x; (这个区间只有一个数)。
那么如何上传值呢。因为我们知道ans[id][z]=ans[id<<1][x]+ans[id<<1|1][z-x];. 所以ans[id][i]= ans[id<<1][i]+ans[id<<1|1][ (i-sum[id<<1]%5+5)%5 ];
#include <cmath>
#include <ctime>
#include <iostream>
#include <string>
#include <vector>
#include <cstdio>
#include <cstdlib>
#include <cstring>
#include <queue>
#include <map>
#include <set>
#include <algorithm>
#include <cctype>
#include <stack>
#include <deque>
using namespace std;
typedef long long LL;
#define eps 10e-9
#define inf 0x3f3f3f3f
const int maxn = 100000+100;
char str[maxn][10];
int op[maxn],y[maxn];
LL ans[maxn<<2][5];
int sum[maxn<<2];
int cur,flag;
void pushup(int id){
for(int i=0;i<5;i++){
ans[id][i]=ans[id<<1][i]+ans[id<<1|1][ (i-sum[id<<1]%5+5)%5 ];
}
}
void update(int id,int l,int r,int pos){
sum[id]+=2*flag-1;
if(l==r){
ans[id][0]=(LL)flag*y[cur];
return ;
}
int m=(l+r)>>1;
if(pos<=m) update(id<<1,l,m,pos);
else update(id<<1|1,m+1,r,pos);
pushup(id);
}
int main(){
int n,tot=0;
scanf("%d",&n);
for(int i=0;i<n;i++){
scanf("%s",str[i]);
if(str[i][0]=='a'||str[i][0]=='d'){
scanf("%d",&op[i]); y[tot++]=op[i];
}
}
sort(y,y+tot);
tot=unique(y,y+tot)-y;
for(int i=0;i<n;i++){
if(str[i][0]=='a'||str[i][0]=='d'){
cur=lower_bound(y,y+tot,op[i])-y;
if(str[i][0]=='a') flag=1,update(1,1,tot,cur);
else flag=0,update(1,1,tot,cur);
}
else printf("%I64d\n",ans[1][2]);
}
return 0;
}