POJ 3481 splay模板

最后撸一发splay。

之前用treap撸的,现在splay也找到感觉了,果然不同凡响,两者之间差别与精妙之处各有其精髓!

真心赞一个!

POJ平衡树的题目还是比较少,只能挑之前做过的捏一捏。但是收获很多,这一天做的题都是有一定普遍性的。

#include <cstdio>
#include <cstring>
#include <iostream>
#include <algorithm>
#include <cstdlib>
#include <cmath>
#include <utility>
#include <vector>
#include <queue>
#include <map>
#include <set>
#define max(x,y) ((x)>(y)?(x):(y))
#define min(x,y) ((x)>(y)?(y):(x))
#define INF 0x3f3f3f3f
#define MAXN 100005

using namespace std;

int cnt=1, rt=0;

struct Tree
{
    int key, size, fa, son[2], num;
    void set(int _key, int _size, int _fa, int _num)
    {
        key=_key;
        size=_size;
        fa=_fa;
        son[0]=son[1]=0;
        num=_num;
    }
}T[MAXN];

inline void PushUp(int x)
{
    T[x].size=T[T[x].son[0]].size+T[T[x].son[1]].size+1;
}

inline void Rotate(int x, int p) //0左旋 1右旋
{
    int y=T[x].fa;
    T[y].son[!p]=T[x].son[p];
    T[T[x].son[p]].fa=y;
    T[x].fa=T[y].fa;
    if(T[x].fa)
        T[T[x].fa].son[T[T[x].fa].son[1] == y]=x;
    T[x].son[p]=y;
    T[y].fa=x;
    PushUp(y);
    PushUp(x);
}

void Splay(int x, int To) //将x节点插入到To的子节点中
{
    while(T[x].fa != To)
    {
        if(T[T[x].fa].fa == To)
            Rotate(x, T[T[x].fa].son[0] == x);
        else
        {
            int y=T[x].fa, z=T[y].fa;
            int p=(T[z].son[0] == y);
            if(T[y].son[p] == x)
                Rotate(x, !p), Rotate(x, p); //之字旋
            else
                Rotate(y, p), Rotate(x, p);    //一字旋
        }
    }
    if(To == 0) rt=x;
}

int find(int key) //返回值为key的节点 若无返回0 若有将其转移到根处
{
    int x=rt;
    while(x && T[x].key != key)
        x=T[x].son[key > T[x].key];
    if(x) Splay(x, 0);
    return x;
}

int prev() //返回比根值小的最大值 若无返回0 若有将其转移到根处
{
    int x=T[rt].son[0];
    if(!x) return 0;
    while(T[x].son[1])
        x=T[x].son[1];
    Splay(x, 0);
    return x;
}

int succ() //返回比根值大的最小值 若无返回0 若有将其转移到根处
{
    int x=T[rt].son[1];
    if(!x) return 0;
    while(T[x].son[0])
        x=T[x].son[0];
    Splay(x, 0);
    return x;
}

void Insert(int key, int num) //插入key 并且将该节点转移到根处
{
    if(!rt)
        T[rt = cnt++].set(key, 1, 0, num);
    else
    {
        int x=rt, y=0;
        while(x)
        {
            y=x;
            x=T[x].son[key > T[x].key];
        }
        T[x = cnt++].set(key, 1, y, num);
        T[y].son[key > T[y].key]=x;
        Splay(x, 0);
    }
}

void Delete(int key) //删除值为key的节点 若有重点只删其中一个 x的前驱移动到根处
{
    int x=find(key);
    if(!x) return;
    int y=T[x].son[0];
    while(T[y].son[1])
        y=T[y].son[1];
    int z=T[x].son[1];
    while(T[z].son[0])
        z=T[z].son[0];
    if(!y && !z)
    {
        rt=0;
        return;
    }
    if(!y)
    {
        Splay(z, 0);
        T[z].son[0]=0;
        PushUp(z);
        return;
    }
    if(!z)
    {
        Splay(y, 0);
        T[y].son[1]=0;
        PushUp(y);
        return;
    }
    Splay(y, 0);
    Splay(z, y);
    T[z].son[0]=0;
    PushUp(z);
    PushUp(y);
}

int GetPth(int p) //获得第p小的节点 并将其转移到根处
{
    if(!rt) return 0;
    int x=rt, ret=0;
    while(x)
    {
        if(p == T[T[x].son[0]].size+1)
            break;
        if(p>T[T[x].son[0]].size+1)
        {
            p-=T[T[x].son[0]].size+1;
            x=T[x].son[1];
        }
        else
            x=T[x].son[0];
    }
    Splay(x, 0);
    return x;
}

int main ()
{
    int p, key, num, x;
    while(scanf("%d", &p) && p)
    {
        switch (p)
        {
            case 1:
                scanf("%d%d", &num, &key);
                Insert(key, num);
                break;
            case 2:
                x=GetPth(T[rt].size);
                if(x)
                {
                    printf("%d\n",T[x].num);
                    Delete(T[x].key);
                }
                else
                    printf("0\n");
                break;
            case 3:
                x=GetPth(1);
                if(x)
                {
                    printf("%d\n",T[x].num);
                    Delete(T[x].key);
                }
                else
                    printf("0\n");
        }
    }
    return 0;
}

之后必须写一篇Splay , Treap , SBT(未学)的总结与模板。

敬请期待!

时间: 2024-12-15 13:09:32

POJ 3481 splay模板的相关文章

POJ 3481 Double Queue(Treap模板题)

Double Queue Time Limit: 1000MS   Memory Limit: 65536K Total Submissions: 15786   Accepted: 6998 Description The new founded Balkan Investment Group Bank (BIG-Bank) opened a new office in Bucharest, equipped with a modern computing environment provid

poj 3468 Splay 树

大二上的时候,写过一个AVL的操作演示,今天一看Splay,发现和AVL其实一样,加上线段树的基础,懒惰标记什么都知道,学起来轻松许多哦 我参考的模板来自这里  http://blog.csdn.net/u013480600/article/list/2 里面有大量的ch[r][0] ch[r][1]等 我建议用宏定义取代,写的时候方括号少打了很多,等做的题多得时候,我再把自己使用的模板发来 #include <cstdio> #include <cstring> #include

splay模板

先贴一份不怎么完善的模板,等刷一些题目熟悉之后再来完善.代码参考自kuangbin及cxlove两位大神. splay的基本功能 题目:维护一个数列,支持以下几种操作: 1. 插入:在当前数列第posi 个数字后面插入tot 个数字:若在数列首位插入,则posi 为0. 2. 删除:从当前数列第posi 个数字开始连续删除tot 个数字. 3. 修改:从当前数列第posi 个数字开始连续tot 个数字统一修改为c . 4. 翻转:取出从当前数列第posi 个数字开始的tot 个数字,翻转后放入原

bzoj 1588 splay模板题

用晚自习学了一下splay模板,没想象中那么难,主要是左旋和右旋可以简化到一个函数里边,减少代码长度... 1 #include<iostream> 2 #include<cstdio> 3 #include<cstring> 4 #include<algorithm> 5 #define maxn 33333 6 #define inf 0x3f3f3f3f 7 #define lc(x) ch[(x)][0] 8 #define rc(x) ch[(x)

bzoj1500(妥妥的splay模板题)

1500: [NOI2005]维修数列 Time Limit: 10 Sec  Memory Limit: 64 MB Submit: 6366  Solved: 1910 [Submit][Status] Description Input 输入文件的第1行包含两个数N和M,N表示初始时数列中数的个数,M表示要进行的操作数目.第2行包含N个数字,描述初始时的数列.以下M行,每行一条命令,格式参见问题描述中的表格. Output 对于输入数据中的GET-SUM和MAX-SUM操作,向输出文件依次

POJ 1113 凸包模板题

上模板. #include <cstdio> #include <cstring> #include <iostream> #include <algorithm> #include <cmath> #include <vector> #include <utility> #include <stack> #include <queue> #include <map> #include

poj 3481 Double Queue STL中map的运用

题意: 维护一个集合,操作有1:加入一个元素,2:删除最大元素,3:删除最小元素. 分析: map本质是个容器,且具有第一个关键字有序的性质,所以用它来水水就好啦~ 代码: //poj 3481 //sep9 #include <iostream> #include <map> using namespace std; map<int,int> mymap; map<int,int>::iterator iter; int main() { int x,su

POJ 1458 LCS模板

LCS模板 存一个 #include "stdio.h" #include "string.h" int main() { char a[1010],b[1010]; int i,j,Max,dp[1010]; while (scanf("%s",a)!=EOF) { scanf("%s",b); memset(dp,0,sizeof(dp)); for (i=0;b[i];i++) { Max=0; for (j=0;a[j

COJ 1002 WZJ的数据结构(二)(splay模板)

我的LCC,LCT,Splay格式终于统一起来了... 另外..这个形式的Splay是标准的Splay(怎么鉴别呢?看Splay函数是否只传了一个变量node就行),刘汝佳小白书的Splay写的真是不想吐槽了,局限性太大,别学... 好了我要去写维修数列了..... 标准Splay模板: 1 #include<iostream> 2 #include<cstdio> 3 #include<cmath> 4 #include<algorithm> 5 #inc