HDU 3487 Play with Chain(伸展树基本操作)

题意:

给定一数组,完成两种操作:

CUT a b c 将区间[a,b]的数删除,并接到新数列的第c个数后面

FLIP a b 将区间[a,b]的数翻转顺序

输出最终的序列

 

题解:

      伸展树的基本操作。

#include<bits/stdc++.h>

using namespace std;
#define keyv ch[ch[root][1]][0]
#define ddd puts("111");
const int maxn = 3e5+99;
int n,q;
int pre[maxn],ch[maxn][2],rev[maxn],sz[maxn],key[maxn],root,tot1;

void update(int r)
{
    if(r==0)return;
    swap(ch[r][0],ch[r][1]);
    rev[r]^=1;
}

void pushdown(int r)
{
    if(rev[r])
    {
        update(ch[r][0]);
        update(ch[r][1]);
        rev[r] = 0;
    }
}

void pushup(int r)
{
    sz[r] = 1 + sz[ch[r][0]] + sz[ch[r][1]];
}
void newnode(int &r,int fa,int k)
{
    r = ++tot1;
    pre[r] = fa;
    key[r] = k;
    rev[r] = ch[r][0] = ch[r][1] = 0;
    sz[r] = 1;
}


void build(int &x,int l,int r,int fa)
{
    if(l>r)return;
    int m = (l+r)>>1;
    newnode(x,fa,m);
    build(ch[x][0],l,m-1,x);
    build(ch[x][1],m+1,r,x);
    pushup(x);
}



void init()
{
    root  = tot1 =0;
    key[root] = ch[root][0] = ch[root][1] =sz[root] = rev[root] = pre[root] = 0;
    newnode(root,0,-1);
    newnode(ch[root][1],root,-1);
    build(keyv,1,n,ch[root][1]);
    pushup(ch[root][1]);
    pushup(root);
}


void rotate(int x,int d)
{
    int y = pre[x];
    pushdown(y);
    pushdown(x);
    ch[y][!d] = ch[x][d];///先搞y
    pre[ch[x][d]] = y;
    if(pre[y]) ch[pre[y]][ch[pre[y]][1]==y]=x;///搞x
    pre[x] = pre[y];
    ch[x][d] = y;
    pre[y] = x;
    pushup(y);
}



void splay(int r,int goal)
{
    while(pre[r] != goal)
    {
        if(pre[pre[r]]==goal)
            rotate(r,ch[pre[r]][0]==r);
        else
        {
            int y = pre[r];
            int d = ch[pre[y]][0]==y;
            if(ch[y][d]==r)
            {
                rotate(r,!d);
                rotate(r,d);
            }
            else
            {
                rotate(y,d);
                rotate(r,d);
            }
        }

    }
    pushup(r);
    if(goal == 0 )root = r;
}

int kth(int r,int k)
{
    pushdown(r);
    int t = sz[ch[r][0]];
    if(k==t+1) return r;
    else if(k <= t)return kth(ch[r][0],k);
    else return kth(ch[r][1],k-t-1);
}



/**本题操作*/
void cut(int a,int b,int c)
{
    splay(kth(root,a),0);//a-1后
    splay(kth(root,b+2),root);//b+1前
    int tmp = keyv;
    keyv = 0;
    pushup(ch[root][1]);
    pushup(root);

    splay(kth(root,c+1),0);//c后
    splay(kth(root,c+2),root);//c+1前
    keyv = tmp;
    pre[keyv] = ch[root][1];
    pushup(ch[root][1]);
    pushup(root);
}

void reverse(int l,int r)
{
    splay(kth(root,l),0);
    splay(kth(root,r+2),root);
    update(keyv);
    pushup(ch[root][1]);
    pushup(root);
}

int cnt;
void print(int r)
{
    if(r==0)return;
    pushdown(r);
    print(ch[r][0]);
    if(cnt<n && key[r]>0)///注意加的边界值。
    {
        cnt++;
        printf("%d%c",key[r],cnt==n?'\n':' ');
    }
    print(ch[r][1]);

}


int main()
{
    while(scanf("%d%d",&n,&q)==2)
    {
        if(n<0 && q<0)break;
        init();
        char op[11];
        int x,y,z;
        while(q--)
        {
            scanf("%s",op);
            if(op[0]=='C')
            {
                scanf("%d%d%d",&x,&y,&z);
                cut(x,y,z);
            }
            else if(op[0]=='F')
            {
                scanf("%d%d",&x,&y);
                reverse(x,y);
            }
            cnt=0;

        }
        print(root);

    }
}



 

 

 

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值