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

看了几天,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][];
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][]],minz[ch[x][]]));
sz[x] = sz[ch[x][]] + sz[ch[x][]] + ;
}
void Update_Rev(int x)
{
if(!x) return ;
swap(ch[x][],ch[x][]);
rev[x] ^= ;
}
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][],lz[x]);
Update_Add(ch[x][],lz[x]);
lz[x] = ;
}
if(rev[x])
{
Update_Rev(ch[x][]);
Update_Rev(ch[x][]);
rev[x] = ;
}
}
void NewNode(int &x,int c)
{
x = ++t;
ch[x][] = ch[x][] = ;
sz[x] = ;
lz[x] = rev[x] = ;
minz[x] = val[x] = c;
}
void makeTree(int &x,int l,int r,int rt)
{
if(l > r) return ;
int m;
m = (l + r)>>;
NewNode(x,num[m]);
makeTree(ch[x][],l,m-,x);
makeTree(ch[x][],m+,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]][] == 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]][] == x);
}
else
{
y = pre[x];
z = pre[y];
pushdown(z);
pushdown(y);
pushdown(x);
flag = (ch[z][] == y);
if(ch[y][flag] == x)
{
Rotate(x,!flag);
Rotate(x,flag);
}
else
{
Rotate(y,flag);
Rotate(x,flag);
}
}
}
pushup(x);
if(goal == ) root = x;
}
void RotateTo(int k,int goal)//将第k个,转到goal下面
{
int x = root;
pushdown(x);
while(sz[ch[x][]] != k)
{
if(k < sz[ch[x][]])
{
x = ch[x][];
}
else
{
k -= (sz[ch[x][]] + );
x = ch[x][];
}
pushdown(x);
}
splay(x,goal);
}
void init(int n)
{
root = t = ;
ch[][] = ch[][] = lz[] = pre[] = ;
val[] = minz[] = ;
rev[] = sz[] = ;//初始化
NewNode(root,-);
NewNode(ch[root][],-);
pre[t] = root;
int i;
for(i = ; i < n; i ++)
{
scanf("%d",&num[i]);
}
makeTree(keyTree,,n-,ch[root][]);//建树
pushup(ch[root][]);
pushup(root);
}
int main()
{
int n,i,x,y,d,m;
char str[];
scanf("%d",&n);
init(n);
scanf("%d",&m);
for(i = ; i < m; i ++)
{
scanf("%s",str);
if(strcmp(str,"ADD") == )
{
scanf("%d%d%d",&x,&y,&d);
RotateTo(x-,);
RotateTo(y+,root);
Update_Add(keyTree,d);
pushup(ch[root][]);
pushup(root);
}
else if(strcmp(str,"INSERT") == )//插入
{
scanf("%d%d",&x,&y);
RotateTo(x,);
RotateTo(x+,root);
NewNode(keyTree,y);
pre[keyTree] = ch[root][];
pushup(ch[root][]);
pushup(root);
}
else if(strcmp(str,"DELETE") == )//删除
{
scanf("%d",&x);
RotateTo(x-,);
RotateTo(x+,root);
pre[keyTree] = ;
keyTree = ;
pushup(ch[root][]);
pushup(root);
}
else if(strcmp(str,"MIN") == )//最值
{
scanf("%d%d",&x,&y);
RotateTo(x-,);
RotateTo(y+,root);
printf("%d\n",minz[keyTree]);
}
else if(strcmp(str,"REVOLVE") == )//右移t位
{
int t,temp;
scanf("%d%d%d",&x,&y,&t);
if(x > y) swap(x,y);
t = t%(y-x+);
if(t < ) t += (y-x+);
if(t == ) continue;
RotateTo(y-t,);
RotateTo(y+,root);
temp = keyTree;
keyTree = ;
RotateTo(x-,);
RotateTo(x,root);
keyTree = temp;
pre[keyTree] = ch[root][];
pushup(ch[root][]);
pushup(root);
}
else
{
scanf("%d%d",&x,&y);//翻转区间
if(x > y) swap(x,y);
RotateTo(x-,);
RotateTo(y+,root);
Update_Rev(keyTree);
pushup(ch[root][]);
pushup(root);
}
}
return ;
}

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][];
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][],ch[x][]);
rev[x] ^= ;
}
void pushdown(int x)
{
if(lz[x])
{
Update_Add(ch[x][],lz[x]);
Update_Add(ch[x][],lz[x]);
lz[x] = ;
}
if(rev[x])
{
Update_Rev(ch[x][]);
Update_Rev(ch[x][]);
rev[x] = ;
}
}
void pushup(int x)
{
sz[x] = sz[ch[x][]] + sz[ch[x][]] + ;
}
void NewNode(int &x,int c,int fa)
{
x = ++t;
ch[x][] = ch[x][] = ;
lz[x] = rev[x] = ;
sz[x] = ;
val[x] = c;
pre[x] = fa;
}
void makeTree(int &x,int l,int r,int rt)
{
if(l > r) return ;
int m = (l + r)>>;
NewNode(x,num[m],rt);
makeTree(ch[x][],l,m-,x);
makeTree(ch[x][],m+,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]][] == 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]][] == x);
}
else
{
y = pre[x];
z = pre[y];
pushdown(z);
pushdown(y);
pushdown(x);
flag = (ch[z][] == y);
if(ch[y][flag] == x)
{
Rotate(x,!flag);
Rotate(x,flag);
}
else
{
Rotate(y,flag);
Rotate(x,flag);
}
}
}
pushup(x);
if(goal == ) root = x;
}
void RotateTo(int k,int goal)
{
int x = root;
pushdown(x);
while(sz[ch[x][]] != k)
{
if(k < sz[ch[x][]])
{
x = ch[x][];
}
else
{
k -= (sz[ch[x][]] + );
x = ch[x][];
}
pushdown(x);
}
splay(x,goal);
}
int get_kth(int k)
{
int x = root;
pushdown(x);
while(sz[ch[x][]] != k)
{
if(k < sz[ch[x][]])
{
x = ch[x][];
}
else
{
k -= (sz[ch[x][]] + );
x = ch[x][];
}
pushdown(x);
}
return val[x];
}
void show(int x)
{
if(x == ) return ;
pushdown(x);
show(ch[x][]);
if(val[x] > )
{
printf("%d ",val[x]);
}
show(ch[x][]);
}
int main()
{
int i,k1,k2,n,m,pos,x,y,d,cas = ;
char str[];
while(scanf("%d%d%d%d",&n,&m,&k1,&k2)!=EOF)
{
if(n == &&m == ) break;
root = t = ;
ch[][] = ch[][] = sz[] = pre[] = ;
rev[] = lz[] = ;
NewNode(root,-,);
NewNode(ch[root][],-,root);
for(i = ;i < n;i ++)
scanf("%d",&num[i]);
makeTree(keyTree,,n-,ch[root][]);
pushup(ch[root][]);
pushup(root);
pos = ;
printf("Case #%d:\n",cas++);
for(i = ;i < m;i ++)
{
scanf("%s",str);
if(str[] == 'a')
{
scanf("%d",&d);
x = pos;
y = pos + k2 -;
if(y <= n)
{
RotateTo(x-,);
RotateTo(y+,root);
Update_Add(keyTree,d);
pushup(ch[root][]);
pushup(root);
}
else
{
RotateTo(x-,);
RotateTo(n+,root);
Update_Add(keyTree,d);
pushup(ch[root][]);
pushup(root); RotateTo(,);
RotateTo(y-n+,root);
Update_Add(keyTree,d);
pushup(ch[root][]);
pushup(root);
}
}
else if(str[] == 'r')
{
x = pos;
y = pos + k1 - ;
if(y <= n)
{
RotateTo(x-,);
RotateTo(y+,root);
Update_Rev(keyTree);
}
else
{
int tb = n-x+;
int ta = k1 - tb; RotateTo(x-,);
RotateTo(n+,root);
Update_Rev(keyTree);
pushup(ch[root][]);
pushup(root); RotateTo(,);
RotateTo(ta+,root);
Update_Rev(keyTree);
int temp = keyTree;
keyTree = ;
pushup(ch[root][]);
pushup(root); RotateTo(x--ta,);
RotateTo(x-ta,root);
keyTree = temp;
pre[keyTree] = ch[root][];
pushup(ch[root][]);
pushup(root); RotateTo(n-ta,);
RotateTo(n+,root);
temp = keyTree;
keyTree = ;
pushup(ch[root][]);
pushup(root); RotateTo(,);
RotateTo(,root);
keyTree = temp;
pre[keyTree] = ch[root][];
pushup(ch[root][]);
pushup(root);
}
}
else if(str[] == 'i')
{
n ++;
scanf("%d",&d);
x = pos;
RotateTo(x,);
RotateTo(x+,root);
NewNode(keyTree,d,ch[root][]);
pushup(ch[root][]);
pushup(root);
}
else if(str[] == 'd')
{ x = pos;
RotateTo(x-,);
RotateTo(x+,root);
keyTree = ;
pushup(ch[root][]);
pushup(root);
if(pos == n) pos = ;
n --;
}
else if(str[] == 'm')
{
scanf("%d",&d);
if(d == )
{
pos ++;
if(pos > n) pos = ;
}
else
{
pos --;
if(pos == ) pos = n;
}
}
else
{
printf("%d\n",get_kth(pos));
}
}
}
return ;
}
/*
5 100 3 2
1 2 3 4 5
m 2
m 2
m 2
reverse
*/

伸展树Splay的更多相关文章

  1. 树-伸展树(Splay Tree)

    伸展树概念 伸展树(Splay Tree)是一种二叉排序树,它能在O(log n)内完成插入.查找和删除操作.它由Daniel Sleator和Robert Tarjan创造. (01) 伸展树属于二 ...

  2. 纸上谈兵: 伸展树 (splay tree)[转]

    作者:Vamei 出处:http://www.cnblogs.com/vamei 欢迎转载,也请保留这段声明.谢谢!  我们讨论过,树的搜索效率与树的深度有关.二叉搜索树的深度可能为n,这种情况下,每 ...

  3. K:伸展树(splay tree)

      伸展树(Splay Tree),也叫分裂树,是一种二叉排序树,它能在O(lgN)内完成插入.查找和删除操作.在伸展树上的一般操作都基于伸展操作:假设想要对一个二叉查找树执行一系列的查找操作,为了使 ...

  4. 高级搜索树-伸展树(Splay Tree)

    目录 局部性 双层伸展 查找操作 插入操作 删除操作 性能分析 完整源码 与AVL树一样,伸展树(Splay Tree)也是平衡二叉搜索树的一致,伸展树无需时刻都严格保持整棵树的平衡,也不需要对基本的 ...

  5. 【BBST 之伸展树 (Splay Tree)】

    最近“hiho一下”出了平衡树专题,这周的Splay一直出现RE,应该删除操作指针没处理好,还没找出原因. 不过其他操作运行正常,尝试用它写了一道之前用set做的平衡树的题http://codefor ...

  6. [Splay伸展树]splay树入门级教程

    首先声明,本教程的对象是完全没有接触过splay的OIer,大牛请右上角.. 首先引入一下splay的概念,他的中文名是伸展树,意思差不多就是可以随意翻转的二叉树 PS:百度百科中伸展树读作:BoGa ...

  7. 伸展树Splay【非指针版】

    ·伸展树有以下基本操作(基于一道强大模板题:codevs维护队列): a[]读入的数组;id[]表示当前数组中的元素在树中节点的临时标号;fa[]当前节点的父节点的编号;c[][]类似于Trie,就是 ...

  8. 伸展树(Splay tree)的基本操作与应用

    伸展树的基本操作与应用 [伸展树的基本操作] 伸展树是二叉查找树的一种改进,与二叉查找树一样,伸展树也具有有序性.即伸展树中的每一个节点 x 都满足:该节点左子树中的每一个元素都小于 x,而其右子树中 ...

  9. ZOJ 3765 Lights (zju March I)伸展树Splay

    ZJU 三月月赛题,当时见这个题目没辙,没学过splay,敲了个链表TLE了,所以回来好好学了下Splay,这道题目是伸展树的第二题,对于伸展树的各项操作有了更多的理解,这题不同于上一题的用指针表示整 ...

  10. [数据结构]伸展树(Splay)

    #0.0 写在前面 Splay(伸展树)是较为重要的一种平衡树,理解起来也依旧很容易,但是细节是真的多QnQ,学一次忘一次,还是得用博客加深一下理解( #1.0 Splay! #1.1 基本构架 Sp ...

随机推荐

  1. SourceTree推送时,增加额外的远程仓库,不用每次都自定义粘贴复制网络

    一.命令行添加 二.软件界面可以查看到结果 更新,以上是代码添加了远程仓库,最近,找到了不用代码,直接在文件夹里写地址来添加的方式.直接上图了.

  2. visio二次开发——图纸解析

    (转发请注明来源:http://www.cnblogs.com/EminemJK/) visio二次开发的案例或者教程,国内真的非常少,这个项目也是花了不少时间来研究visio的相关知识,困难之所以难 ...

  3. 2015.4.23 贪吃蛇、canvas动画,各种上传工具,url信息匹配以及最全前端面试题等

    1.面向对象贪吃蛇   2.css中:hover 改变图片 页面加载完 第一次鼠标移入会闪一下 这是为啥? 解决方法:你把两张图合成一张图或者是先把图片加载到页面上,然后再hover出来. 解析:图片 ...

  4. linux 根据文件大小查找文件

    inux下的find命令用来查找文件,通过man find就知道它是无所不能的.所以按照文件大小来查找文件就不在话下.从man find搜索size,可以看到如下信息: -size n[cwbkMG] ...

  5. 用jsp的application写一个记录用户登陆网站的数量

    </head><body><%int i = 0;Object number = application.getAttribute("num");if ...

  6. jq小插件--方便设置css属性

    $.fn.extend({ setCss:function(name,value){ $(this).css(name,value) } }) 调用方式,如: $('.login-btn').setC ...

  7. PHP 动态生成验证码

    ……机器人会在网站中搜寻允许他们插入广告的输入表单,在虚拟世界没有什么能阻挡它们胡作非为.这些机器人效率极高,完全不关心所攻击的表单的本来用途.它们唯一的目标就是用它们的垃圾广告覆盖你的内容,残忍地为 ...

  8. 及时取消代码中的AsyncTask

    在一个Activity页面,如果发起了AsyncTask任务,然后页面离开/销毁了,此时如果doInBackground没执行完,会有两个问题: 1, AsyncTask白白消耗资源,结果已经用不上了 ...

  9. python 单步调试初探(未完待续)

    pdb 调试: import pdb pdb.set_trace()     pudb 调试: http://python.jobbole.com/82638/

  10. Servlet 之 HttpServlet

    package cn.jiemoxiaodi.http; import java.io.IOException; import javax.servlet.GenericServlet; import ...