伸展树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
原文地址:https://www.cnblogs.com/naix-x/p/3784227.html