hdu 4288 Coder (线段树)
题目大意:
三个操作,
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; }
补充:软件开发 , C++ ,