hdu 4288 五颗线段树

来源:互联网 发布:linux公社 ftp 编辑:程序博客网 时间:2024/05/22 04:37

http://acm.hdu.edu.cn/showproblem.php?pid=4288

/*题目:给出一个有序集合,3种操作。插入一个数,删除一个数,都保证序列有序。以及求和其中求和是将下标%5==3的所有数求和解法:   五颗线段树!!   前段时间刚做了,十颗线段树!!现在再做五颗的就哑火了!!!比赛时,不敢做!!后面的更简单题目没有出来,   这个题目就不敢做了!!我表示弱校伤不起,弱菜伤不起!!*/#include<iostream>#include<cstdio>#include<cstring>#include<algorithm>#include<memory.h>using namespace std;const int maxn=100002;#define lson rt<<1,l,mid#define rson rt<<1|1,mid+1,r__int64 sum[maxn<<2][6];char op[maxn][20];int num[maxn<<2],n,a[maxn],idx[maxn];//表示左移距离void pushUp(int rt){    num[rt]=num[rt<<1]+num[rt<<1|1];    int id=num[rt<<1];    for(int i=0; i<5; i++)    {        sum[rt][i]=sum[rt<<1][i];    }    for(int i=0; i<5; i++)    {        sum[rt][(i+id)%5]+=sum[rt<<1|1][i];    }}void build(int rt,int l,int r){     num[rt]=0;    for(int i=0; i<5; i++) sum[rt][i]=0;    if(l==r) return;    int mid=(l+r)>>1;    build(lson);    build(rson);}void updata(int rt,int l,int r,int pos,int op)//op=1 表示 add; op=0 表示 del;{    if(l==r)    {        num[rt]=op;        sum[rt][1]=op*idx[l];        return ;    }    int mid=(l+r)>>1;    if(pos<=mid)        updata(lson,pos,op);    else        updata(rson,pos,op);    pushUp(rt);}int main(){    while(scanf("%d",&n)!=EOF)    {        int i,j,k=0;        for(i=0; i<n; i++)        {            scanf("%s",&op[i]);            if(op[i][0]!='s')            {                scanf("%d",&a[i]);                if(op[i][0]=='a')                {                    idx[++k]=a[i];                }            }        }        sort(idx+1,idx+k+1);//因为没有排序WA了无数次!!        k=unique(idx+1,idx+k+1)-(idx+1);        build(1,1,k);        for(i=0; i<n; i++)        {            int pos=upper_bound(idx+1,idx+k+1,a[i])-(idx+1);            if(op[i][0]=='a')            {                updata(1,1,k,pos,1);            }            else if(op[i][0]=='d')            {                updata(1,1,k,pos,0);            }            else printf("%I64d\n",sum[1][3]);        }    }    return 0;}