伸展树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 ...
随机推荐
- Node.js入门笔记(4):文件系统(fs)
文件系统(FileSystem) 文件系统模块 对于文件无外乎创建修改添加. File System - 文件系统模块 - require('fs') fs模块是核心模块,需要使用require导入后 ...
- Unity unsafe
http://answers.unity3d.com/questions/23307/is-it-impossible-to-use-the-code-with-keyword-unsa.html 可 ...
- Spring系列之Spring常用注解总结
传统的Spring做法是使用.xml文件来对bean进行注入或者是配置aop.事物,这么做有两个缺点:1.如果所有的内容都配置在.xml文件中,那么.xml文件将会十分庞大:如果按需求分开.xml文件 ...
- Android Studio的配置问题——Intel HAXM is required to run this AVD,VT-x is disabled in BIOS;
Intel HAXM is required to run this AVD,VT-x is disabled in BIOS;Enable VT-x in your BIOS security se ...
- Ubuntu下su被拒绝
ubuntu@ubuntu:~$ sudo passwd root输入新的 UNIX 密码: 重新输入新的 UNIX 密码: passwd:已成功更新密码前提是你肯定得知道当前用户的密码. 然后登录: ...
- 【WIN10】绑定x:Bind
在WP8.WP8中,我们知道有一个绑定{Binding},而在Win10中,新增了一个绑定{x:Bind} x:Bind :为编译时绑定 ,内存.内存相对于传统绑定都有优化 特性: 1.为强类型 ...
- Discuzx系统 CSS 编码规范,CSS属性书写顺序
1. 属性写在一行内,属性之间.属性名和值之间以及属性与“{}”之间须有空格,例如:.class { width: 400px; height: 300px; } 2. 属性的书写顺序: ...
- Eclipse安装Freemarker插件
方法一:手动安装 手动安装没有成功 步骤: 1. 下载freemarker-ide : http://sourceforge.net/projects/freemarker-ide/files/ 2. ...
- 内网安全工具之cain劫持工具
满足arp的条件为:目标IP为动态IP(arp -a查看) 下载地址:cain4.9.zip 官网:http://www.oxid.it/cain.html 08专版:cain08安装版 把cain下 ...
- java程序打包成jar
1. 建立文件夹:proj,在该文件夹下建立3个子文件夹:lib,src 2. 在lib文件夹中放置依赖的jar包 3. 在src中放置类文件:com.cnjava.demo.Main.java 4. ...