码迷,mamicode.com
首页 > 其他好文 > 详细

伸展树Splay

时间:2014-06-13 14:36:52      阅读:213      评论:0      收藏:0      [点我收藏+]

标签:style   class   blog   code   http   tar   

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

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

POJ 3580 SuperMemo

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

Splay模板

bubuko.com,布布扣
#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

 

伸展树Splay,布布扣,bubuko.com

伸展树Splay

标签:style   class   blog   code   http   tar   

原文地址:http://www.cnblogs.com/naix-x/p/3784227.html

(0)
(0)
   
举报
评论 一句话评论(0
登录后才能评论!
© 2014 mamicode.com 版权所有  联系我们:gaon5@hotmail.com
迷上了代码!