题目大意:
三个操作,
add 在集合中插入一个数
del 在集合中删除一个数
sum 求出在这个集合中下标模 5 得 3的数的和
都保证序列有序
思路:
先把所有的数字输入进来 然后离散化 那么我们可以得到一个数组 就是在操作中会出现的要你插入的数
然后我们就可以开始update 我们把他们分别插入离散化之后的所对应的位置
然后线段树就维护这个区间 对5取模 为 0 1 2 3 4 的位置的所有的和 只是仅对于这个区间哦。并不是说他的下标
比如说 当S==E的时候 这个区间只有一个数 那么这个位置下标模5 就是1
再者说 e-s+1 == 2 的时候 这个区间有两个数 那么第一个数就是mod 5==1 的 第二个就是==2的。。
然后cnt维护的是这个区间有多少个。
#include <iostream>
#include <cstdio>
#include <algorithm>
#define lson num<<1,s,mid
#define rson num<<1|1,mid+1,e
#define maxn 100005
typedef long long LL;
using namespace std;
LL tre[maxn<<2][5];
LL cnt[maxn<<2];
struct node
{
char op[10];
LL w;
}P[maxn];
LL X[maxn];
void build(int num,int s,int e)
{
int mid=(s+e)>>1;
cnt[num]=0;
memset(tre[num],0,sizeof(tre[num]));
if(s==e)
{
return;
}
build(lson);
build(rson);
}
void pushup(int num)
{
for(int i=0;i<5;i++)
tre[num][i]=tre[num<<1][i]+tre[num<<1|1][((i-cnt[num<<1])%5+5)%5];//这个地方有点难得想- =
}
void update(int num,int s,int e,int pos,int val,int k)
{
cnt[num] += 2*k-1;
if(s==e)
{
if(k==1)tre[num][1]=val;
else tre[num][1]=0;
return;
}
int mid=(s+e)>>1;
if(pos<=mid)update(lson,pos,val,k);
else update(rson,pos,val,k);
pushup(num);
}
int main()
{
int n;
while(scanf("%d",&n)!=EOF)
{
int tot=1;
for(int i=1;i<=n;i++)
{
scanf("%s",&P[i].op);
if(P[i].op[0]!='s')
{
scanf("%I64d",&P[i].w);
X[tot++]=(LL)P[i].w;
}
}
sort(X+1,X+tot);
tot=unique(X+1,X+tot)-(X+1);
build(1,1,tot);
for(int i=1;i<=n;i++)
{
if(P[i].op[0]!='s')
{
int pos = lower_bound(X+1,X+tot+1,P[i].w)-X;
if(P[i].op[0]=='a')update(1,1,tot,pos,P[i].w,1);
else update(1,1,tot,pos,P[i].w,0);
}
else printf("%I64d\n",tre[1][3]);
}
}
return 0;
}