Splay 区间反转

懒标记处理 向下传时交换左右子树

#include<iostream>
#include<cstdio>
#include<algorithm>
#define N 100005
using namespace std;
struct Node {int ls,rs,sum,flip,sz,fa,data;}t[N];
int a[N],num=0,m,n,root=0;
void pushdown(int k) {
    if(t[k].flip) {
        t[t[k].ls].flip^=1;t[t[k].rs].flip^=1;
        t[k].flip=0;swap(t[k].ls,t[k].rs);
    }
}
void pushup(int k){
    t[k].sz=t[t[k].ls].sz+t[t[k].rs].sz+1;
    t[k].sum=t[t[k].ls].sum+t[t[k].rs].sum+t[k].data;
}
void lturn(int x){
    int y=t[x].fa,z=t[y].fa;
    t[y].rs=t[x].ls;t[t[x].ls].fa=y;
    t[x].ls=y;t[y].fa=x;t[x].fa=z;
    if(t[z].ls==y) t[z].ls=x;
    else t[z].rs=x;
}
void rturn(int x){
    int y=t[x].fa,z=t[y].fa;
    t[y].ls=t[x].rs;t[t[x].rs].fa=y;
    t[x].rs=y;t[y].fa=x;t[x].fa=z;
    if(t[z].rs==y) t[z].rs=x;
    else t[z].ls=x;
}
void splay(int x,int f){
    while(t[x].fa!=f){
        int y=t[x].fa;
        pushdown(y);pushdown(x);
        if(t[y].ls==x) rturn(x);
        else if(t[y].rs==x) lturn(x);
        pushup(y);pushup(x);
    }
    if(f==0) root=x;
}
void insert(int x){
    t[++num].data=x;t[num].sz=1;t[num].sum=x;t[num].fa=root;
    t[num].ls=t[num].rs=0;t[root].rs=num;
    splay(num,0);pushup(num);
}
int getxth(int k,int x){
    pushdown(k);
    int wtf=t[t[k].ls].sz+1;
    if(wtf==x) return k;
    if(wtf<x) return getxth(t[k].rs,x-wtf);
    if(wtf>x) return getxth(t[k].ls,x);
}
void reverse(int k,int x,int y){
    splay(getxth(root,x-1),0);splay(getxth(root,y+1),root);
    t[t[t[root].rs].ls].flip^=1;
}
int getsum(int k,int x,int y){
    splay(getxth(root,x-1),0);splay(getxth(root,y+1),root);
    return t[t[t[root].rs].ls].sum;
}
int main(){
    freopen("in.txt","r",stdin);
    freopen("out.txt","w",stdout);
    scanf("%d%d",&n,&m);
    insert(0);
    for(int i=1;i<=n;i++) {
        scanf("%d",&a[i]);
        insert(a[i]);
    }
    insert(0);
    for(int i=1;i<=m;i++){
        char s[10];int x,y;
        scanf("%s%d%d",s,&x,&y);
        if(s[0]=='R') reverse(root,x+1,y+1);
        if(s[0]=='S') printf("%d\n",getsum(root,x+1,y+1));
    }
    return 0;
}

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值