hdu 3487 Play with Chain splay 区间翻转,插入,删除

题目链接点这里

都是先经典操作。。

但是写的时候要注意,,经过子节点的地方,,,都要pushdown()啊啊啊啊

#include<iostream>
#include<cstdio>
using namespace std;
#define INF 0x3f3f3f3f
#define INFLL 0x3f3f3f3f3f3f3f3f
#define FIN freopen("input.txt","r",stdin);
#define mem(x,y) memset(x,y,sizeof(x));
typedef unsigned long long ULL;
typedef long long LL;
#define MX 555555
//数组splay 区间翻转,区间插入,区间删除
int n,m;
int son[MX][2],fa[MX],siz[MX],root,val[MX],lazy[MX],cnt;
void Pushup(int rt) {
    int ls=son[rt][0],rs=son[rt][1];
    siz[rt]=1;
    if(ls) siz[rt]+=siz[ls];
    if(rs) siz[rt]+=siz[rs];
}
void Pushdown(int rt) {
    if(lazy[rt]) {
        if(son[rt][0])lazy[son[rt][0]]^=1;
        if(son[rt][1])lazy[son[rt][1]]^=1;
        swap(son[rt][0],son[rt][1]);
        lazy[rt]=0;
    }
}
int New_nod(int f,int v) {
    cnt++;
    son[cnt][0]=son[cnt][1]=0;
    fa[cnt]=f,siz[cnt]=1,val[cnt]=v,lazy[cnt]=0;
    return cnt;
}
void Splay_init() {
    cnt=0;
    root=New_nod(0,-INF);//先加了2个边界点
    son[root][1]=New_nod(root,INF);
    Pushup(root);
}
void Rotate(int x,int c) { //c==0代表右旋
    int nxtf=fa[fa[x]],f=fa[x];
    Pushdown(f),Pushdown(x);
    if(nxtf!=0)son[nxtf][son[nxtf][0]!=f]=x;
    fa[x]=nxtf;
    son[f][c]=son[x][!c];
    fa[son[x][!c]]=f;
    son[x][!c]=f;
    fa[f]=x;
    Pushup(f);
}
void Splay(int x,int y) { //把x旋转为y的子节点,首先要确保y是x的祖先
    Pushdown(x);
    while(fa[x]!=y) {
        int f=fa[x];
        int c1=(son[fa[f]][0]==f),c2=(son[f][0]==x);
        if(fa[f]==y)Rotate(x,!c2);
        else {
            if(c1^c2)Rotate(x,!c2),Rotate(x,c2);
            else Rotate(f,!c1),Rotate(x,!c1);;
        }
    }
    Pushup(x);
    if(!y)root=x;
}
int path[MX],pathcnt;
void print(int rt) {
    if(rt==0)return;
    Pushdown(rt);
    print(son[rt][0]);
    path[pathcnt++]=val[rt];
    print(son[rt][1]);
}
int Select(int x) { //找第x点,x不包括边界
    x++;
    int now=root;
    while(1) {
        Pushdown(now);
        if(siz[son[now][0]]+1==x)return now;
        else if(siz[son[now][0]]+1<x)x-=siz[son[now][0]]+1,now=son[now][1];
        else now=son[now][0];
    }
}
void Update(int l,int r) {
    int x=Select(l-1),y=Select(r+1);
    Splay(x,0),Splay(y,x);
    lazy[son[y][0]]^=1;
    //Pushup(y),Pushup(x);
}
int temp[MX];
int Build(int l,int r,int f ) {
    if(l>r)return 0;
    int m=(l+r)>>1;
    int rt=New_nod(f,temp[m]);
    son[rt][0]=Build(l,m-1,rt),son[rt][1]=Build(m+1,r,rt);
    Pushup(rt);
    return rt;
}
void Insert(int w,int n) { //在第w位置之后,插入n个数
    int rt=Build(1,n,0);
    int x=Select(w),y=Select(w+1);
    Splay(x,0),Splay(y,x);
    son[y][0]=rt,fa[rt]=y;
    Pushup(y),Pushup(x);
}
void Cut(int l,int r,int to) { //吧下标为[l,r]的数移到to后面
    int x=Select(l-1),y=Select(r+1);
    Splay(x,0),Splay(y,x);
    int rt=son[y][0];
    son[y][0]=0;
    Pushup(y),Pushup(x);
    x=Select(to),y=Select(to+1);
    Splay(x,0),Splay(y,x);
    son[y][0]=rt,fa[rt]=y;
    Pushup(y),Pushup(x);
}
int main() {
    FIN;
    while(cin>>n>>m&&n>0) {
        Splay_init();
        for(int i=1; i<=n; i++)temp[i]=i;
        Insert(0,n);
        for(int i=1; i<=m; i++) {
            char s[111];
            int a,b,c;
            scanf("%s",s);
            if(s[0]=='C') {
                scanf("%d%d%d",&a,&b,&c);
                Cut(a,b,c);
            } else {
                scanf("%d%d",&a,&b);
                Update(a,b);
            }
        }
        pathcnt=0;
        print(root);
        for(int i=1; i<pathcnt-1; i++)
            printf("%d%c",path[i],i==pathcnt-2?'\n':' ');
    }
    return 0;
}


评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值