Codeforces 85D Sum of Medians

来源:互联网 发布:手机黑客攻击软件 编辑:程序博客网 时间:2024/06/04 18:14

题意:

有n个操作,add x表示向集合添加元素x,del x表示删除集合中的x元素,sum表示求集合所有下标i%5==3的元素之和,注意里的元素都是有序且无重复的。

思路:

线段树+离线处理,单点更新,O(1)查询。为每个节点存储两种信息,一种为当树向上更新时右区间需要平移的个数mov,另一种为ans[i]表示该区间内所有下标%5==i的元素的和。然后树的向上更新操作就为

sum[rt].mov=(sum[rt<<1].mov+sum[rt<<1|1].mov)%5;

for(int i=0;i<5;i++){

sum[rt].ans[i]=sum[rt<<1].ans[i]+sum[rt<<1|1].ans[(i-sum[rt<<1].mov+5)%5];

}

接下来是离线处理问题,即先把问题存在数组中。由于这集合的元素都是有序且无重复的。所以我们可以借助set来离散化元素值,使其按从小到大的顺序对应一个位置,最后才能方便地在树上进行加入、删除操作。

#include<cstdio>#include<set>#include<map>#include<cstring>using namespace std;typedef __int64 LL;const int MAX=1e5+5;struct Node{int mov;LL ans[5];}sum[MAX<<2];struct Que{int id,x;}Q[MAX];int n;set<int> s;map<int,int> pos;char op[5];void PushUp(int rt){sum[rt].mov=(sum[rt<<1].mov+sum[rt<<1|1].mov)%5;for(int i=0;i<5;i++){sum[rt].ans[i]=sum[rt<<1].ans[i]+sum[rt<<1|1].ans[(i-sum[rt<<1].mov+5)%5];}}void UpDate(int pos,int c,int l,int r,int rt){if(l==r){if(c>0){sum[rt].mov=1;sum[rt].ans[1]=c;}else{sum[rt].mov=0;sum[rt].ans[1]=0;}return;}int mid=(l+r)>>1;if(pos<=mid) UpDate(pos,c,l,mid,rt<<1);else UpDate(pos,c,mid+1,r,rt<<1|1);PushUp(rt);}int main(){scanf("%d",&n);for(int i=1;i<=n;i++){scanf("%s",op);if(op[0]=='a'){scanf("%d",&Q[i].x);s.insert(Q[i].x);Q[i].id=0;}if(op[0]=='d'){scanf("%d",&Q[i].x);Q[i].id=1;}if(op[0]=='s'){Q[i].id=2;}}int cnt=1;set<int>::iterator it;for(it=s.begin();it!=s.end();it++){pos[(*it)]=cnt++;}cnt--;memset(sum,0,sizeof(sum));for(int i=1;i<=n;i++){if(Q[i].id==0){UpDate(pos[Q[i].x],Q[i].x,1,cnt,1);}if(Q[i].id==1){UpDate(pos[Q[i].x],-Q[i].x,1,cnt,1);}if(Q[i].id==2){printf("%I64d\n",sum[1].ans[3]);}}return 0;}


0 0
原创粉丝点击