• 伸展树Splay


    新学的,其实吧,就那么回事....

    看了几天,splay处理序列问题,真的非常厉害,翻转,插入,删除,线段树实现不了的功能,splay用起来很方便。

    POJ 3580 SuperMemo

    这题基本就是检验模板的题,各种操作都有,错了好多次,发现以前写的代码有错了的,数据水点,给水过了,注意pushup。

    Splay模板

    #include <cstdio>
    #include <cstring>
    #include <map>
    #include <algorithm>
    #include <iostream>
    using namespace std;
    #define N 500000
    #define INF 0x7FFFFFFF
    #define keyTree (ch[ ch[root][1] ][0])
    int pre[N];
    int lz[N];
    int rev[N];
    int ch[N][2];
    int val[N];
    int minz[N];
    int sz[N];
    int num[N];
    int root,t;
    void pushup(int x)
    {
        minz[x] = min(val[x],min(minz[ch[x][0]],minz[ch[x][1]]));
        sz[x] = sz[ch[x][0]] + sz[ch[x][1]] + 1;
    }
    void Update_Rev(int x)
    {
        if(!x) return ;
        swap(ch[x][1],ch[x][0]);
        rev[x] ^= 1;
    }
    void Update_Add(int x,int d)
    {
        if(!x) return ;
        val[x] += d;
        minz[x] += d;
        lz[x] += d;
    }
    void pushdown(int x)
    {
        if(lz[x])
        {
            Update_Add(ch[x][0],lz[x]);
            Update_Add(ch[x][1],lz[x]);
            lz[x] = 0;
        }
        if(rev[x])
        {
            Update_Rev(ch[x][0]);
            Update_Rev(ch[x][1]);
            rev[x] = 0;
        }
    }
    void NewNode(int &x,int c)
    {
        x = ++t;
        ch[x][0] = ch[x][1]  = 0;
        sz[x] = 1;
        lz[x] = rev[x] = 0;
        minz[x] = val[x] = c;
    }
    void makeTree(int &x,int l,int r,int rt)
    {
        if(l > r) return ;
        int m;
        m = (l + r)>>1;
        NewNode(x,num[m]);
        makeTree(ch[x][0],l,m-1,x);
        makeTree(ch[x][1],m+1,r,x);
        pre[x] = rt;
        pushup(x);
    }
    void Rotate(int x,int flag)//左旋 右旋
    {
        int y = pre[x];
        pushdown(y);
        pushdown(x);
        ch[y][!flag] = ch[x][flag];
        pre[ch[x][flag]] = y;
        pre[x] = pre[y];
        if(pre[x])
            ch[pre[y]][ ch[pre[y]][1] == y] = x;
        ch[x][flag] = y;
        pre[y] = x;
        pushup(y);
    }
    void splay(int x,int goal)//把x转到goal下面
    {
        int y,z,flag;
        while(pre[x] != goal)
        {
            if(pre[pre[x]] == goal)
            {
                pushdown(pre[x]);
                pushdown(x);
                Rotate(x,ch[pre[x]][0] == x);
            }
            else
            {
                y = pre[x];
                z = pre[y];
                pushdown(z);
                pushdown(y);
                pushdown(x);
                flag = (ch[z][0] == y);
                if(ch[y][flag] == x)
                {
                    Rotate(x,!flag);
                    Rotate(x,flag);
                }
                else
                {
                    Rotate(y,flag);
                    Rotate(x,flag);
                }
            }
        }
        pushup(x);
        if(goal == 0) root = x;
    }
    void RotateTo(int k,int goal)//将第k个,转到goal下面
    {
        int x = root;
        pushdown(x);
        while(sz[ch[x][0]] != k)
        {
            if(k < sz[ch[x][0]])
            {
                x = ch[x][0];
            }
            else
            {
                k -= (sz[ch[x][0]] + 1);
                x = ch[x][1];
            }
            pushdown(x);
        }
        splay(x,goal);
    }
    void init(int n)
    {
        root = t = 0;
        ch[0][0] = ch[0][1] = lz[0] = pre[0] = 0;
        val[0] = minz[0] = 0;
        rev[0] = sz[0] = 0;//初始化
        NewNode(root,-1);
        NewNode(ch[root][1],-1);
        pre[t] = root;
        int i;
        for(i = 0; i < n; i ++)
        {
            scanf("%d",&num[i]);
        }
        makeTree(keyTree,0,n-1,ch[root][1]);//建树
        pushup(ch[root][1]);
        pushup(root);
    }
    int main()
    {
        int n,i,x,y,d,m;
        char str[101];
        scanf("%d",&n);
        init(n);
        scanf("%d",&m);
        for(i = 0; i < m; i ++)
        {
            scanf("%s",str);
            if(strcmp(str,"ADD") == 0)
            {
                scanf("%d%d%d",&x,&y,&d);
                RotateTo(x-1,0);
                RotateTo(y+1,root);
                Update_Add(keyTree,d);
                pushup(ch[root][1]);
                pushup(root);
            }
            else if(strcmp(str,"INSERT") == 0)//插入
            {
                scanf("%d%d",&x,&y);
                RotateTo(x,0);
                RotateTo(x+1,root);
                NewNode(keyTree,y);
                pre[keyTree] = ch[root][1];
                pushup(ch[root][1]);
                pushup(root);
            }
            else if(strcmp(str,"DELETE") == 0)//删除
            {
                scanf("%d",&x);
                RotateTo(x-1,0);
                RotateTo(x+1,root);
                pre[keyTree] = 0;
                keyTree = 0;
                pushup(ch[root][1]);
                pushup(root);
            }
            else if(strcmp(str,"MIN") == 0)//最值
            {
                scanf("%d%d",&x,&y);
                RotateTo(x-1,0);
                RotateTo(y+1,root);
                printf("%d
    ",minz[keyTree]);
            }
            else if(strcmp(str,"REVOLVE") == 0)//右移t位
            {
                int t,temp;
                scanf("%d%d%d",&x,&y,&t);
                if(x > y) swap(x,y);
                t = t%(y-x+1);
                if(t < 0) t += (y-x+1);
                if(t == 0) continue;
                RotateTo(y-t,0);
                RotateTo(y+1,root);
                temp = keyTree;
                keyTree = 0;
                RotateTo(x-1,0);
                RotateTo(x,root);
                keyTree = temp;
                pre[keyTree] = ch[root][1];
                pushup(ch[root][1]);
                pushup(root);
            }
            else
            {
                scanf("%d%d",&x,&y);//翻转区间
                if(x > y) swap(x,y);
                RotateTo(x-1,0);
                RotateTo(y+1,root);
                Update_Rev(keyTree);
                pushup(ch[root][1]);
                pushup(root);
            }
        }
        return 0;
    }
    View Code

     HDU 4453 Looploop

    这题是现场赛的题目啊...非常麻烦,不过想好了,就没什么了,主要是翻转哪里。

    #include <cstdio>
    #include <cstring>
    #include <map>
    #include <algorithm>
    #include <iostream>
    using namespace std;
    #define N 300000
    #define INF 0x7FFFFFFF
    #define keyTree (ch[ ch[root][1] ][0])
    int ch[N][2];
    int pre[N];
    int val[N];
    int lz[N];
    int sz[N];
    int rev[N];
    int num[N];
    int root,t;
    void Update_Add(int x,int d)
    {
        if(!x) return ;
        lz[x] += d;
        val[x] += d;
    }
    void Update_Rev(int x)
    {
        if(!x) return ;
        swap(ch[x][0],ch[x][1]);
        rev[x] ^= 1;
    }
    void pushdown(int x)
    {
        if(lz[x])
        {
            Update_Add(ch[x][0],lz[x]);
            Update_Add(ch[x][1],lz[x]);
            lz[x] = 0;
        }
        if(rev[x])
        {
            Update_Rev(ch[x][0]);
            Update_Rev(ch[x][1]);
            rev[x] = 0;
        }
    }
    void pushup(int x)
    {
        sz[x] = sz[ch[x][0]] + sz[ch[x][1]] + 1;
    }
    void NewNode(int &x,int c,int fa)
    {
        x = ++t;
        ch[x][0] = ch[x][1] = 0;
        lz[x] = rev[x] = 0;
        sz[x] = 1;
        val[x] = c;
        pre[x] = fa;
    }
    void makeTree(int &x,int l,int r,int rt)
    {
        if(l > r) return ;
        int m = (l + r)>>1;
        NewNode(x,num[m],rt);
        makeTree(ch[x][0],l,m-1,x);
        makeTree(ch[x][1],m+1,r,x);
        pushup(x);
    }
    void Rotate(int x,int flag)
    {
        int y = pre[x];
        pushdown(y);
        pushdown(x);
        ch[y][!flag] = ch[x][flag];
        pre[ch[x][flag]] = y;
        pre[x] = pre[y];
        if(pre[x])
        ch[pre[y]][ ch[pre[y]][1] == y ] = x;
        ch[x][flag] = y;
        pre[y] = x;
        pushup(y);
    }
    void splay(int x,int goal)
    {
        int y,z,flag;
        while(pre[x] != goal)
        {
            if(pre[pre[x]] == goal)
            {
                pushdown(pre[x]);
                pushdown(x);
                Rotate(x,ch[pre[x]][0] == x);
            }
            else
            {
                y = pre[x];
                z = pre[y];
                pushdown(z);
                pushdown(y);
                pushdown(x);
                flag = (ch[z][0] == y);
                if(ch[y][flag] == x)
                {
                    Rotate(x,!flag);
                    Rotate(x,flag);
                }
                else
                {
                    Rotate(y,flag);
                    Rotate(x,flag);
                }
            }
        }
        pushup(x);
        if(goal == 0) root = x;
    }
    void RotateTo(int k,int goal)
    {
        int x = root;
        pushdown(x);
        while(sz[ch[x][0]] != k)
        {
            if(k < sz[ch[x][0]])
            {
                x = ch[x][0];
            }
            else
            {
                k -= (sz[ch[x][0]] + 1);
                x = ch[x][1];
            }
            pushdown(x);
        }
        splay(x,goal);
    }
    int get_kth(int k)
    {
        int x = root;
        pushdown(x);
        while(sz[ch[x][0]] != k)
        {
            if(k < sz[ch[x][0]])
            {
                x = ch[x][0];
            }
            else
            {
                k -= (sz[ch[x][0]] + 1);
                x = ch[x][1];
            }
            pushdown(x);
        }
        return val[x];
    }
    void show(int x)
    {
        if(x == 0) return ;
        pushdown(x);
        show(ch[x][0]);
        if(val[x] > 0)
        {
            printf("%d ",val[x]);
        }
        show(ch[x][1]);
    }
    int main()
    {
        int i,k1,k2,n,m,pos,x,y,d,cas = 1;
        char str[100];
        while(scanf("%d%d%d%d",&n,&m,&k1,&k2)!=EOF)
        {
            if(n == 0&&m == 0) break;
            root = t = 0;
            ch[0][0] = ch[0][1] = sz[0] = pre[0] = 0;
            rev[0] = lz[0] = 0;
            NewNode(root,-1,0);
            NewNode(ch[root][1],-1,root);
            for(i = 0;i < n;i ++)
            scanf("%d",&num[i]);
            makeTree(keyTree,0,n-1,ch[root][1]);
            pushup(ch[root][1]);
            pushup(root);
            pos = 1;
            printf("Case #%d:
    ",cas++);
            for(i = 0;i < m;i ++)
            {
                scanf("%s",str);
                if(str[0] == 'a')
                {
                    scanf("%d",&d);
                    x = pos;
                    y = pos + k2 -1;
                    if(y <= n)
                    {
                        RotateTo(x-1,0);
                        RotateTo(y+1,root);
                        Update_Add(keyTree,d);
                        pushup(ch[root][1]);
                        pushup(root);
                    }
                    else
                    {
                        RotateTo(x-1,0);
                        RotateTo(n+1,root);
                        Update_Add(keyTree,d);
                        pushup(ch[root][1]);
                        pushup(root);
    
                        RotateTo(0,0);
                        RotateTo(y-n+1,root);
                        Update_Add(keyTree,d);
                        pushup(ch[root][1]);
                        pushup(root);
                    }
                }
                else if(str[0] == 'r')
                {
                    x = pos;
                    y = pos + k1 - 1;
                    if(y <= n)
                    {
                        RotateTo(x-1,0);
                        RotateTo(y+1,root);
                        Update_Rev(keyTree);
                    }
                    else
                    {
                        int tb = n-x+1;
                        int ta = k1 - tb;
    
                        RotateTo(x-1,0);
                        RotateTo(n+1,root);
                        Update_Rev(keyTree);
                        pushup(ch[root][1]);
                        pushup(root);
    
                        RotateTo(0,0);
                        RotateTo(ta+1,root);
                        Update_Rev(keyTree);
                        int temp = keyTree;
                        keyTree = 0;
                        pushup(ch[root][1]);
                        pushup(root);
    
    
    
                        RotateTo(x-1-ta,0);
                        RotateTo(x-ta,root);
                        keyTree = temp;
                        pre[keyTree] = ch[root][1];
                        pushup(ch[root][1]);
                        pushup(root);
    
                        RotateTo(n-ta,0);
                        RotateTo(n+1,root);
                        temp = keyTree;
                        keyTree = 0;
                        pushup(ch[root][1]);
                        pushup(root);
    
                        RotateTo(0,0);
                        RotateTo(1,root);
                        keyTree = temp;
                        pre[keyTree] = ch[root][1];
                        pushup(ch[root][1]);
                        pushup(root);
                    }
                }
                else if(str[0] == 'i')
                {
                    n ++;
                    scanf("%d",&d);
                    x = pos;
                    RotateTo(x,0);
                    RotateTo(x+1,root);
                    NewNode(keyTree,d,ch[root][1]);
                    pushup(ch[root][1]);
                    pushup(root);
                }
                else if(str[0] == 'd')
                {
    
                    x = pos;
                    RotateTo(x-1,0);
                    RotateTo(x+1,root);
                    keyTree = 0;
                    pushup(ch[root][1]);
                    pushup(root);
                    if(pos == n) pos = 1;
                    n --;
                }
                else if(str[0] == 'm')
                {
                    scanf("%d",&d);
                    if(d == 2)
                    {
                        pos ++;
                        if(pos > n) pos = 1;
                    }
                    else
                    {
                        pos --;
                        if(pos == 0) pos = n;
                    }
                }
                else
                {
                    printf("%d
    ",get_kth(pos));
                }
            }
        }
        return 0;
    }
    /*
    5 100 3 2
    1 2 3 4 5
    m 2
    m 2
    m 2
    reverse
    */
    View Code
  • 相关阅读:
    LeetCode -- Rectangle Area
    【转】VS常用快捷键
    C++中include<> 与 include" " 的区别
    浅析_tmain() 与 main() 函数的区别
    VS2013下配置OpenCV 3.0.0 &&& VS2013下配置Opencv2.4.9
    LeetCode -- Valid Parenthese
    杂想 · 警醒
    LeetCode -- Length of Last Word
    LeetCode -- Valid Sudoku
    LeetCode -- Binary Tree Level Order Traversal II
  • 原文地址:https://www.cnblogs.com/naix-x/p/3784227.html
Copyright © 2020-2023  润新知