Codeforces 85D. Sum of Medians (线段树)

题意:

        三种操作,1.加入一个数,2,删除一个数,3,询问经过排序以后,所有下标 mod5 m o d 5 余3的数的和

思路:

        注意到,当我们加入一个数以后,会让所有后面的数后移一位,删除会使得后面全部前移一位,每次移动都使得下标变化1,所以我们用线段树维护5个值,分别是当前区间下标余数为0,1,2,3,4的值的和,每次加入或删除树,我们只需要把后面的这五个数变换即可(例如我们加入一个树,后面的坐标全部加一,所以原本余数为1的值变成原本余数为0的值)
        总结一下,首先读入所有操作,离散出所有数字,每次操作都将后面的数字移动一位,利用lazy节省时间,利用数值交换实现下标的移动

错误及反思:

代码:

#include<bits/stdc++.h>
using namespace std;
#define lson l,m,rt<<1
#define rson m+1,r,rt<<1|1
const int N = 100100;
long long segtree[N<<2][5];
int lazy[N<<2];
int num[N<<2];
vector<int> id;
int n;
int getid(int x){return lower_bound(id.begin(),id.end(),x)-id.begin()+1;}
struct ope{
    char t[10];
    int x;
}op[N];


void pushup(int rt){
    segtree[rt][0]=segtree[rt<<1][0]+segtree[rt<<1|1][0];
    segtree[rt][1]=segtree[rt<<1][1]+segtree[rt<<1|1][1];
    segtree[rt][2]=segtree[rt<<1][2]+segtree[rt<<1|1][2];
    segtree[rt][3]=segtree[rt<<1][3]+segtree[rt<<1|1][3];
    segtree[rt][4]=segtree[rt<<1][4]+segtree[rt<<1|1][4];
}

void pushdown(int rt){
    if(lazy[rt]!=0){
        lazy[rt<<1]+=lazy[rt]; lazy[rt<<1]%=5;
        lazy[rt<<1|1]+=lazy[rt]; lazy[rt<<1|1]%=5;
        while(lazy[rt]){
            swap(segtree[rt<<1][0],segtree[rt<<1][1]); swap(segtree[rt<<1][0],segtree[rt<<1][2]);
            swap(segtree[rt<<1][0],segtree[rt<<1][3]); swap(segtree[rt<<1][0],segtree[rt<<1][4]);

            swap(segtree[rt<<1|1][0],segtree[rt<<1|1][1]); swap(segtree[rt<<1|1][0],segtree[rt<<1|1][2]);
            swap(segtree[rt<<1|1][0],segtree[rt<<1|1][3]); swap(segtree[rt<<1|1][0],segtree[rt<<1|1][4]);
            lazy[rt]--;
        }
    }
}

void change(int x,int v,int l,int r,int rt){
    if(l==r){
        num[rt]+=v;
        return ;
    }
    int m=l+r>>1;
    if(x<=m) change(x,v,lson);
    else change(x,v,rson);
    num[rt]=num[rt<<1]+num[rt<<1|1];
}

int getnum(int L,int R,int l,int r,int rt){
    if(L<=l&&R>=r) return num[rt];
    int m=l+r>>1,ans=0;
    if(L<=m) ans+=getnum(L,R,lson);
    if(R>m) ans+=getnum(L,R,rson);
    return ans;
}

void update(int x,int op,int num,int l,int r,int rt){
    if(l==r){
        if(op==1)
            segtree[rt][(num+1)%5]+=op*id[l-1];
        else segtree[rt][(num)%5]+=op*id[l-1];
        return ;
    }
    pushdown(rt);
    int m=l+r>>1;
    if(m>=x){
        update(x,op,num,lson);
        if(op==1){
            lazy[rt<<1|1]++; lazy[rt<<1|1]%=5;
            swap(segtree[rt<<1|1][0],segtree[rt<<1|1][1]); swap(segtree[rt<<1|1][0],segtree[rt<<1|1][2]);
            swap(segtree[rt<<1|1][0],segtree[rt<<1|1][3]); swap(segtree[rt<<1|1][0],segtree[rt<<1|1][4]);
        }
        else{
            lazy[rt<<1|1]+=4; lazy[rt<<1|1]%=5;
            swap(segtree[rt<<1|1][0],segtree[rt<<1|1][4]); swap(segtree[rt<<1|1][0],segtree[rt<<1|1][3]);
            swap(segtree[rt<<1|1][0],segtree[rt<<1|1][2]); swap(segtree[rt<<1|1][0],segtree[rt<<1|1][1]);
        }

    }
    else update(x,op,num,rson);
    pushup(rt);
    return ;
}

int main(){
    scanf("%d",&n);
    for(int i=0;i<n;i++){
        scanf("%s",op[i].t);
        if(op[i].t[0]=='a'||op[i].t[0]=='d'){
            scanf("%d",&op[i].x);
            id.push_back(op[i].x);
        }
    }
    sort(id.begin(),id.end()),id.erase(unique(id.begin(),id.end()),id.end());
    for(int i=0;i<n;i++){
        if(op[i].t[0]=='s')
            printf("%lld\n",segtree[1][3]);
        else if(op[i].t[0]=='a'){
            int x=getid(op[i].x);
            update(x,1,getnum(1,x,1,id.size(),1),1,id.size(),1);
            change(x,1,1,id.size(),1);
        }
        else{
            int x=getid(op[i].x);
            update(x,-1,getnum(1,x,1,id.size(),1),1,id.size(),1);
            change(x,-1,1,id.size(),1);
        }
    }
}
  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值