伸展树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\n",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:\n",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\n",get_kth(pos));

            }

        }

    }

    return 0;

}

/*

5 100 3 2

1 2 3 4 5

m 2

m 2

m 2

reverse

*/
View Code

 

 

你可能感兴趣的:(play)