伸展树Splay
新学的,其实吧,就那么回事....
看了几天,splay处理序列问题,真的非常厉害,翻转,插入,删除,线段树实现不了的功能,splay用起来很方便。
这题基本就是检验模板的题,各种操作都有,错了好多次,发现以前写的代码有错了的,数据水点,给水过了,注意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 ;
}
这题是现场赛的题目啊...非常麻烦,不过想好了,就没什么了,主要是翻转哪里。
#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的更多相关文章
- 树-伸展树(Splay Tree)
伸展树概念 伸展树(Splay Tree)是一种二叉排序树,它能在O(log n)内完成插入.查找和删除操作.它由Daniel Sleator和Robert Tarjan创造. (01) 伸展树属于二 ...
- 纸上谈兵: 伸展树 (splay tree)[转]
作者:Vamei 出处:http://www.cnblogs.com/vamei 欢迎转载,也请保留这段声明.谢谢! 我们讨论过,树的搜索效率与树的深度有关.二叉搜索树的深度可能为n,这种情况下,每 ...
- K:伸展树(splay tree)
伸展树(Splay Tree),也叫分裂树,是一种二叉排序树,它能在O(lgN)内完成插入.查找和删除操作.在伸展树上的一般操作都基于伸展操作:假设想要对一个二叉查找树执行一系列的查找操作,为了使 ...
- 高级搜索树-伸展树(Splay Tree)
目录 局部性 双层伸展 查找操作 插入操作 删除操作 性能分析 完整源码 与AVL树一样,伸展树(Splay Tree)也是平衡二叉搜索树的一致,伸展树无需时刻都严格保持整棵树的平衡,也不需要对基本的 ...
- 【BBST 之伸展树 (Splay Tree)】
最近“hiho一下”出了平衡树专题,这周的Splay一直出现RE,应该删除操作指针没处理好,还没找出原因. 不过其他操作运行正常,尝试用它写了一道之前用set做的平衡树的题http://codefor ...
- [Splay伸展树]splay树入门级教程
首先声明,本教程的对象是完全没有接触过splay的OIer,大牛请右上角.. 首先引入一下splay的概念,他的中文名是伸展树,意思差不多就是可以随意翻转的二叉树 PS:百度百科中伸展树读作:BoGa ...
- 伸展树Splay【非指针版】
·伸展树有以下基本操作(基于一道强大模板题:codevs维护队列): a[]读入的数组;id[]表示当前数组中的元素在树中节点的临时标号;fa[]当前节点的父节点的编号;c[][]类似于Trie,就是 ...
- 伸展树(Splay tree)的基本操作与应用
伸展树的基本操作与应用 [伸展树的基本操作] 伸展树是二叉查找树的一种改进,与二叉查找树一样,伸展树也具有有序性.即伸展树中的每一个节点 x 都满足:该节点左子树中的每一个元素都小于 x,而其右子树中 ...
- ZOJ 3765 Lights (zju March I)伸展树Splay
ZJU 三月月赛题,当时见这个题目没辙,没学过splay,敲了个链表TLE了,所以回来好好学了下Splay,这道题目是伸展树的第二题,对于伸展树的各项操作有了更多的理解,这题不同于上一题的用指针表示整 ...
- [数据结构]伸展树(Splay)
#0.0 写在前面 Splay(伸展树)是较为重要的一种平衡树,理解起来也依旧很容易,但是细节是真的多QnQ,学一次忘一次,还是得用博客加深一下理解( #1.0 Splay! #1.1 基本构架 Sp ...
随机推荐
- 每日学习笔记:js中可以直接用id名调用的问题?
在JavaScript中,标准的id选择器调用语法是: document.getElementById('myid').style.width = pc + "%"; 但是,今天发 ...
- Path Sum
需如下树节点求和 5 / \ 4 8 / / \ 11 13 4 / \ / \ 7 2 5 1 JavaScript实现 window ...
- github提交代码时,报permission denied publickey
在像github提交代码时,报permission denied publickey. 查找了一下,可能是因为github的key失效了. 按照以下步骤,重新生成key. ssh-keygen 一路默 ...
- 错误 Metadata file 'C:\Common\bin\Debug\Common.dll' could not be found
一个通用方法de类库/总是报这个错误/很明显就是没有成功生成程序集... 但是就是找不到哪里的错误!!!! 如果是代码写错的话,可能会直接提示在哪个文件中哪行代码写错了,然后dll生成不了,但是这个错 ...
- TypePerf.exe使用命令查找计数器
TypePerf.exe是一个命令行工具,包括把Windows操作系统的性能计数器数据输出到命令窗口或写入到支持该功能的日志文件格式中. 通过以下两个参数获取计数器信息: -q [object] 列出 ...
- java生产者/消费者模式实现——一生产者一消费者(操作值)
胶多不粘话多不甜,直接上代码: 生产者类: /** * Created by 51304 on 2016/2/28. */ public class P { private String lock; ...
- T-SQL备忘-表连接更新
1.update a inner join b on a.id=b.id set a.name=b.name where ... 2.update table1 set a.name = b.na ...
- idea之internal java compiler error
启动错误:Error:java: Compilation failed: internal java compiler error 解决:将圈选地方改为对应的jdk版本即可
- javascript基础03
javascript基础03 1. 算术运算符 后增量/后减量运算符 ++ ,-- 比较运算符 ( >, <, >=, <=, ==, !=,===,!== ) 逻辑运算符( ...
- 【Maven】解决缺少Jar包问题
解决办法:进入项目的根目录(即 pom.xml文件所在的目录)执行:mvn dependency:copy-dependencies完成后进入eclipse,发现项目不再报错前提条件:1,安装了mav ...