题意:给三种操作,一种是想有序序列中加一个数,一个是向有序序列中删除一个数,还有一种是求这个有序序列中mod 5==3的数据之和。
思路:建立一颗线段树,每个线段树都有6个域,mod[0...4]还有一个num[]用来记录每个区间内的个数。难点在于更新时。
#include <iostream>
#include <cstdio>
#include <algorithm>
using namespace std;
#define lson l,m,rt<<1
#define rson m+1,r,rt<<1|1
typedef long long ll;
const int mm=111111;
int num[mm<<2],tab[mm],a[mm];
char ch[mm][10];
struct na
{
ll mod[5];
}sum[mm<<2];
void build(int l,int r,int rt)
{
num[rt]=0;
for(int i=0;i<5;i++)
sum[rt].mod[i]=0;
if(l==r)
return;
int m=(l+r)>>1;
build(lson);
build(rson);
}
int bin(int key,int l,int r)
{
while(l<=r)
{
int m=(l+r)>>1;
if(tab[m]==key) return m;
else if(tab[m]>key) r=m-1;
else l=m+1;
}
}
void pushup(int rt)
{
int i;
num[rt]=num[rt<<1]+num[rt<<1|1];
for(i=0;i<5;i++)
sum[rt].mod[i]=sum[rt<<1].mod[i];
int lx=num[rt<<1];
for(i=0;i<5;i++)
sum[rt].mod[(i+lx)%5]+=sum[rt<<1|1].mod[i];
}
void update(int pos,int val,int l,int r,int rt)
{
if(l==r)
{
num[rt]=val;
sum[rt].mod[1]=val*tab[l];
return;
}
int m=(l+r)>>1;
if(pos<=m) update(pos,val,lson);
else update(pos,val,rson);
pushup(rt);
}
int main()
{
int n,i,j,cnt;
while(~scanf("%d",&n))
{
cnt=0;
for(i=0;i<n;i++)
{
scanf("%s",ch[i]);
if(ch[i][0]!='s')
{
scanf("%d",&a[i]);
if(ch[i][0]=='a') tab[++cnt]=a[i];
}
}
sort(tab+1,tab+1+cnt);
j=1;
for(i=2;i<=cnt;i++)
if(tab[i]!=tab[j]) tab[++j]=tab[i];
build(1,j,1);
for(i=0;i<n;i++)
{
if(ch[i][0]=='a')
{
int pos=bin(a[i],1,j);
update(pos,1,1,j,1);
}
if(ch[i][0]=='d')
{
int pos=bin(a[i],1,j);
update(pos,0,1,j,1);
}
if(ch[i][0]=='s')
{
printf("%I64d\n",sum[1].mod[3]);
}
}
}
return 0;
}