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

看了几天,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. Redis总结(四)Redis 的持久化

    前面已经总结了Redis 的安装和使用今天讲下Redis 的持久化. redis跟memcached类似,都是内存数据库,不过redis支持数据持久化,也就是说redis可以将内存中的数据同步到磁盘来 ...

  2. ubuntu 系统使用

    1.ubuntu的鼠标,用起来总是感觉比windows的快一点儿,可以用以下命令来调整为默认的 root@admin-pc:~$ xset m default 2.mysql默认不允许远程连接,可以在 ...

  3. maven install时报错Failed to execute goal org.apache.maven.plugins:maven-compiler-plugin:2.3.2:compile

    首先检查父项目,子项目的jdk版本是否一致,编码格式是否一致我的问题就错在了编码格式上,父项目用的是UTF-8,子项目新建的,默认GBK这时,使用maven install命令出错 提示:[INFO] ...

  4. 2015.4.25-2015.5.1 字符串去重,比例圆设计,中奖机和canvas橡皮擦效果等

    1.字符串去重,html模板取值   2.javascript正则表达式之$1...$9   3.jquery插件   4.返回上一页并刷新 解决方法: <a href ="javas ...

  5. Windows - 杀死占用某个端口号的进程

    Windows不像Linux,Unix那样,ps -ef 查出端口和进程号,然后根据进程号直接kill进程. Windows根据端口号杀死进程要分三步: 第一步 根据 端口号 寻找 进程号 C:\&g ...

  6. JavaScript获取浏览器高度和宽度值(documentElement,clientHeight,offsetHeight,scrollHeight,scrollTop,offsetParent,offsetY,innerHeight)

    IE中: document.body.clientWidth ==> BODY对象宽度 document.body.clientHeight ==> BODY对象高度 document.d ...

  7. PHP保留2位小数 格式化小数、浮点数

    JS保留两位小数例子 四舍五入使用函数 toFixed() <html> <head> </head> <script language="java ...

  8. ASM:《X86汇编语言-从实模式到保护模式》第15章:任务切换

    15章其实应该是和14章相辅相成的(感觉应该是作者觉得14章内容太多了然后切出来了一点).任务切换和14章的某些概念是分不开的. ★PART1:任务门与任务切换的方法 1. 任务管理程序 14章的时候 ...

  9. 利用Photos 框架搭建美图秀秀相册选择器

    简介:Photos框架是iOS8.0后推出的一个新的用于对系统相册进行相关操作的,在iOS8.0之前,开发中只能使用AssetsLibrary框架来访问移动设备的图片库.本文中不再对AssetsLib ...

  10. 网页Loading效果

    问题描述:由于项目要求在页面提交以及加载的时候,有短暂的卡顿,需要用loading过渡. 1.下一个页面加载的时候实现: base-loading.js //获取浏览器页面可见高度和宽度 var _P ...