UVA 11922 伸展树Splay 第一题
上次ZOJ月赛碰到一个题目要求对序列中的某个区间求gcd,并且还要随时对某位数字进行修改 插入 删除,当时马上联想到线段树,但是线段树不支持增删,明显还是不可以的,然后就敲了个链表想暴力一下,结果TLE。那天回来后搜了下题解,发现大家都在说平衡树 Splay,就好好学了下,这玩意还是挺难学的,我看了好久。最后还是从网上找了三篇论文打印了下,趁着TCG讲数据库的时候(这课真的好催眠)好好看了下,才搞清楚基本的Splay操作
这是第一道Splay题目,基本上是照着模板敲出来的,没办法,第一次学,好多地方不熟练,不过整个过程我已经形成了一个条理了,这倒是一大收获
由于自己的粗心,好几个细节错了,调试了好久。。Sigh!
#include <cstdio>
#include <cstring>
#include <algorithm>
#define N 150010
using namespace std;
struct Node
{
Node *ch[],*pre;
int val,size;
bool rev;
void update()
{
size=ch[]->size+ch[]->size+;
}
void pushdown();
}Tnull,*null=&Tnull;//这里要把null设置为指针,由于下面基本上用的指针,有大量判断是否相等,必须统一类型。
void Node::pushdown()//该函数涉及null,不能写在结构体里,否则被认为null未被定义,只能用写在外面这样的方式来实现
{
if (rev){
swap(ch[],ch[]);
for (int i=;i<;i++)
if (ch[i]!=null) ch[i]->rev=!ch[i]->rev;
rev=;
}
}
Node nodePool[N];
Node *root,*cur;
int n,m;
Node * newNode(int v,Node* f) //从点池中生成新的点
{
cur->ch[]=cur->ch[]=null;
cur->size=;
cur->val=v;
cur->rev=;
cur->pre=f;
return cur++;
}
Node*build(int l,int r,Node* f)//建树操作。
{
if (l>r) return null;
int mid=(l+r)>>;
//printf("%d %d\n",l,r);
Node* temp=newNode(mid,f);
temp->ch[]=build(l,mid-,temp);
temp->ch[]=build(mid+,r,temp);
temp->update();
return temp; }
void rotate(Node* x,int c) //旋转操作,分情况讨论下就行
{
Node* y=x->pre;
y->pushdown();
x->pushdown();
// puts("judge1");
y->ch[!c]=x->ch[c];
if (x->ch[c]!=null)
x->ch[c]->pre=y;
x->pre=y->pre;
// puts("judge2");
if (y->pre!=null){
// puts("deep1");
//if (y->pre==null) puts("Yes");
//printf("%d\n",y->pre->size);
if (y->pre->ch[]==y){
//puts("deep2"); y->pre->ch[]=x;
// puts("deep3");
}
else{
// puts("deep4");
y->pre->ch[]=x;
// puts("deep5");
}
}
// puts("judge3");
x->ch[c]=y;
y->pre=x;
y->update();
x->update();
if (y==root)
root=x;
//puts("is there?");
}
void Splay(Node* x,Node* f)//Splay过程说白了就是把x节点旋转到f下面,分情况讨论一下就可以
{
x->pushdown();
while (x->pre!=f)
{
//puts("Why?");
if (x->pre->pre==f)
{
if (x->pre->ch[]==x)
rotate(x,);
else
rotate(x,);
// puts("pass1");
}
else
{
//puts("pass2");
Node *y=x->pre;
Node *z=y->pre;
if (z->ch[]==y)
{
// puts("pass3");
if (y->ch[]==x)
rotate(y,),rotate(x,);
else
rotate(x,),rotate(x,);
// puts("pass4");
}
else
{
// puts("pass5");
//rotate(y,1);
if (y->ch[]==x){
// puts("pass6");
rotate(x,);
rotate(x,);
//puts("pass7");
}
else
{
// puts("pass8");
rotate(y,),rotate(x,);
}
// puts("pass10");
}
//puts("pass7");
}
// puts("isblock?");
}
x->update();
}
void select(int k,Node* f) //把第k个节点旋转到f的下面
{
int tmp;
Node* x=root;
//x->pushdown();
k++; //因为建树的时候插入了0点作为缓冲点,因此实际的点要++以消除该点的影响。
for (;;){
x->pushdown();
tmp=x->ch[]->size;
if (k==tmp+) break;
if (k<=tmp)
x=x->ch[];
else{
k-=tmp+;
x=x->ch[];
}
}
//puts("Test");
Splay(x,f);
// puts("t");
}
Node* get(int l,int r)
{
select(l-,null);
//puts("pass");
select(r+,root);
// puts("pass");
return root->ch[]->ch[];
}
void reverses(int a,int b) //翻转操作
{
Node* o=get(a,b);
//puts("Pass");
o->rev=!o->rev;
Splay(o,null); }
void split(int l,int r,Node* &s)//切除翻转序列,并把切除的序列用s保存起来
{
Node*temp=get(l,r);
root->ch[]->ch[]=null;
root->ch[]->update();
root->update();
s=temp;
}
void cut(int l,int r) //把切除的序列接到序列末端,只需把序列的最右边点移到根节点,再设置它的右孩子为刚刚切除的序列即可
{
Node *tmp;
split(l,r,tmp);
select(root->size-,null);//把自己手动设置的第n+1点移植到顶点,这样做的原因是防止他干扰,不移它的话,最右点就不是第n点,而是n+1点了
select(root->size-,root);
root->ch[]->ch[]=tmp;
tmp->pre=root->ch[];
root->ch[]->update();
root->update();
}
void init(int num)
{
cur=nodePool;
root=null;
root=newNode(,null);
root->ch[]=newNode(num+,root);//设置两个缓冲点,我刚刚还在犹豫n+1点是否需要,经实测确实需要,因为程序中随时要探测自己的子孩子,如果不设置,可能会溢出
root->ch[]->ch[]=build(,num,root->ch[]);
root->update();//
}
void output()
{
for (int i=;i<=n;i++)
{
select(i,null); //输出某点即把该点旋转到根节点再输出
printf("%d\n",root->val);
}
}
int main()
{
int a,b;
while (scanf("%d%d",&n,&m)!=EOF)
{
init(n);
//output();
while (m--)
{
scanf("%d%d",&a,&b);
if (a>b) swap(a,b);
reverses(a,b);
cut(a,b);
}
output();
}
}
UVA 11922 伸展树Splay 第一题的更多相关文章
- ZOJ 3765 Lights (zju March I)伸展树Splay
ZJU 三月月赛题,当时见这个题目没辙,没学过splay,敲了个链表TLE了,所以回来好好学了下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)也是平衡二叉搜索树的一致,伸展树无需时刻都严格保持整棵树的平衡,也不需要对基本的 ...
- UVA 11922 Permutation Transformer —— splay伸展树
题意:根据m条指令改变排列1 2 3 4 … n ,每条指令(a, b)表示取出第a~b个元素,反转后添加到排列尾部 分析:用一个可分裂合并的序列来表示整个序列,截取一段可以用两次分裂一次合并实现,粘 ...
- [Splay伸展树]splay树入门级教程
首先声明,本教程的对象是完全没有接触过splay的OIer,大牛请右上角.. 首先引入一下splay的概念,他的中文名是伸展树,意思差不多就是可以随意翻转的二叉树 PS:百度百科中伸展树读作:BoGa ...
- 伸展树Splay【非指针版】
·伸展树有以下基本操作(基于一道强大模板题:codevs维护队列): a[]读入的数组;id[]表示当前数组中的元素在树中节点的临时标号;fa[]当前节点的父节点的编号;c[][]类似于Trie,就是 ...
- POJ 3580 - SuperMemo - [伸展树splay]
题目链接:http://poj.org/problem?id=3580 Your friend, Jackson is invited to a TV show called SuperMemo in ...
随机推荐
- 格雷码(Grey Code)生成规则
(1) Grey码在FPGA实际应用中是实用的码,在8421BCD码累加计数器中,如果寄存器需要发生多位(两位或者以上)的跳变,会出现中间态,这样作为组合逻辑的输入是不稳妥的. 下面看两个中间态的例子 ...
- SpringBoot-集成通用mapper
SpringBoot-集成通用mapper SpringBoot-集成通用mapper 我们在SpringBoot中整合了MyBatis,但是大量重复的增删改查还是很头疼的问题,MyBatis也给 ...
- Netty 模型
Demo代码 使用Maven的话请在pom.xml中注入netty依赖 <!-- https://mvnrepository.com/artifact/io.netty/netty-all -- ...
- ssh服务启动失败 /var/empty must be owned by root and not group or world-writable.
输入 /etc/rc.d/init.d/sshd start 启动sshd服务,报如下错误: /var/empty must be owned by root and not group or wor ...
- cf 785#
23333再次水惨了..(心酸啊) A题呵呵呵呵呵 #include<cstdio> #include<iostream> using namespace std; int m ...
- 一百零三、SAP中常量的定义CONSTANTS
一.代码如下 二.运行效果如下
- phpStudy配置站点解决各种不能访问问题(本地可www.xx.com访问)
1.配置站点:打开phpStudy->其他选项菜单->站点域名管理 2.配置站点:打开phpStudy->其他选项菜单->打开hosts(www访问重点) 3.在apache的 ...
- idea自定义快捷鍵
一 生成方法注释 1. File -> Settings... 2. Editor -> Live Templates,点击最右边的+ 3. 依自己情况选择,我这里选择的 Live Te ...
- UVA - 1262 Password(密码)(暴力枚举)
题意:给两个6行5列的字母矩阵,找出满足如下条件的“密码”:密码中的每个字母在两个矩阵的对应列中均出现.给定k(1<=k<=7777),你的任务是找出字典序第k小的密码.如果不存在,输出N ...
- POJ 1276:Cash Machine 多重背包
Cash Machine Time Limit: 1000MS Memory Limit: 10000K Total Submissions: 30006 Accepted: 10811 De ...