zoukankan      html  css  js  c++  java
  • hdu3487 伸展树(区间搬移 区间旋转)

        对于区间旋转使用lazy思想就能解决。然后对于区间搬移,先把a-1结点做根,b+1作为它的右孩子,这样ch[ch[root][1]][0]就是区间[a,b],现将他取出。

    然后在将当前的树伸展,把c结点转到根,c+1作为它的右孩子,这样c+1结点的左孩子就是空的,直接将上次取出的作为c+1结点的做孩子即可。

    #include<queue>
    #include<stack>
    #include<cmath>
    #include<cstdio>
    #include<cstring>
    #include<iostream>
    #include<algorithm>
    #define INF 99999999
    #define ll __int64
    #define lson l,m,rt<<1
    #define rson m+1,r,rt<<1|1
    #define key_value ch[ch[root][1]][0]
    using namespace std;
    const int MAXN = 3*100010;
    int pre[MAXN],ch[MAXN][2],siz[MAXN],key[MAXN],rev[MAXN],root,tot1;
    int n;
    void Treavel(int x)
    {
        if(x)
        {
            Treavel(ch[x][0]);
            printf("结点%2d:左儿子 %2d 右儿子 %2d 父结点 %2d size=%2d key=%2d
    ",x,ch[x][0],ch[x][1],pre[x],siz[x],key[x]);
            Treavel(ch[x][1]);
        }
    }
    void debug()
    {
        printf("root:%d
    ",root);
        Treavel(root);
    }
    void Newnode(int &rt,int pa,int k)
    {
        rt = ++tot1;
        pre[rt] = pa;
        siz[rt] = 1;
        rev[rt] = 0;
        key[rt] = k;
        ch[rt][0] = ch[rt][1] = 0;
    }
    void pushup(int rt)
    {
        siz[rt] = siz[ch[rt][0]] + siz[ch[rt][1]] + 1;
    }
    void pushdown(int rt)
    {
        if(rev[rt]){
            rev[ch[rt][0]] ^= 1;
            rev[ch[rt][1]] ^= 1;
            swap(ch[rt][0],ch[rt][1]);
            rev[rt] = 0;
        }
    }
    void build(int &rt,int l,int r,int pa)
    {
        if(l > r)
            return ;
        int m = (l+r)/2;
        Newnode(rt,pa,m);
        build(ch[rt][0],l,m-1,rt);
        build(ch[rt][1],m+1,r,rt);
        pushup(rt);
    }
    void Init()
    {
        tot1 = root = 0;
        pre[root] = siz[root] = key[root] = rev[root] = 0;
        ch[root][0] = ch[root][1] = 0;
        Newnode(root,0,-1);
        Newnode(ch[root][1],root,-1);
        build(key_value,1,n,ch[root][1]);
        pushup(ch[root][1]);
        pushup(root);
    }
    void Rotate(int rt,int kind)
    {
        int y = pre[rt];
        pushdown(y);
        pushdown(rt);
        ch[y][!kind] = ch[rt][kind];
        pre[ch[rt][kind]] = y;
        if(pre[y]){
            ch[pre[y]][ch[pre[y]][1]==y] = rt;
        }
        pre[rt] = pre[y];
        ch[rt][kind] = y;
        pre[y] = rt;
        pushup(y);
    }
    void splay(int rt,int goal)
    {
        pushdown(rt);
        while(pre[rt] != goal)
        {
            if(pre[pre[rt]] == goal){
                pushdown(pre[rt]);
                pushdown(rt);
                Rotate(rt,ch[pre[rt]][0]==rt);
            }
            else {
                pushdown(pre[pre[rt]]);
                pushdown(pre[rt]);
                pushdown(rt);
                int y = pre[rt];
                int kind = ch[pre[y]][0]==y;
                if(ch[y][kind] == rt){
                    Rotate(rt,!kind);
                    Rotate(rt,kind);
                }
                else {
                    Rotate(y,kind);
                    Rotate(rt,kind);
                }
            }
        }
        if(goal == 0)
            root = rt;
        pushup(rt);
    }
    int Get_kth(int rt,int k)
    {
        pushdown(rt);
        int t = siz[ch[rt][0]] + 1;
        if(t == k)
            return rt;
        else if(t > k){
            return Get_kth(ch[rt][0],k);
        }
        else {
            return Get_kth(ch[rt][1],k-t);
        }
        pushup(rt);
    }
    void cut(int x,int y,int z)
    {
        splay(Get_kth(root,x),0);
        splay(Get_kth(root,y+2),root);
        //debug();
        int tmp = key_value;
        key_value = 0;
        pushup(ch[root][1]);
        pushup(root);
        splay(Get_kth(root,z+1),0);
        splay(Get_kth(root,z+2),root);
        //debug();
        key_value = tmp;
        pre[tmp] = ch[root][1];
        pushup(ch[root][1]);
        pushup(root);
        //debug();
    }
    int flag;
    void display(int rt)
    {
        if(rt == 0)
            return ;
        pushdown(rt);
        display(ch[rt][0]);
        if(!flag && rt !=1 && rt != 2){
            flag = 1;
            printf("%d",key[rt]);
        }
        else if(rt !=1 && rt != 2){
            printf(" %d",key[rt]);
        }
        display(ch[rt][1]);
    }
    int main()
    {
        int i,j,m;
        while(~scanf("%d%d",&n,&m),n!=-1&&m!=-1)
        {
            Init();
            char work[10];
            while(m--)
            {
                scanf("%s",work);
                if(work[0] == 'F'){
                    int x,y;
                    scanf("%d%d",&x,&y);
                    splay(Get_kth(root,x),0);
                    splay(Get_kth(root,y+2),root);
                    rev[key_value] ^= 1;
                    //debug();
                }
                else {
                    int x,y,z;
                    scanf("%d%d%d",&x,&y,&z);
                    cut(x,y,z);
                }
            }
            //debug();
            flag = 0;
            display(root);
            cout<<endl;
        }
    }
  • 相关阅读:
    Nodejs学习笔记
    Multiple SSH keys for different github accounts
    深入Node.js的模块机制
    Yoga S5
    Nodejs
    gulp & webpack整合
    git subtree:无缝管理通用子项目
    javascript功能插件大集合,写前端的亲们记得收藏
    Python简单的制作图片验证码
    用CSS3/JS绘制自己想要的按钮
  • 原文地址:https://www.cnblogs.com/sweat123/p/5141435.html
Copyright © 2011-2022 走看看