UVA 11922 Permutation Transformer (Splay树)
题意:
给一个序列,是从1~n共n个的自然数,接下来又m个区间,对于每个区间[a,b],从第a个到第b个从序列中分离出来,翻转后接到尾部。输出最后的序列。
思路:
这次添加了Split和Merge两个基本操作,还有个比较困难的翻转操作。翻转操作只需要将需要翻转的序列独立成树,给根加上翻转标记之后再直接插到另外由前后两棵树组成的树上。但是在做一些操作的时候可能会遇到已经标记了翻转的子树,比如splay时,如果不顾flip标记,直接带flip标记的点伸展到根,会就会跟其他没有标记的节点混合了,而一个点如果带flip标记,其实标记的是它的两个孩子是需要翻转,此时如果来个无标记的孩子替换了某个孩子,就会造成错误。所以必须在splay之前完成翻转。
#include <bits/stdc++.h>
#define pii pair<int,int>
#define INF 0x3f7f7f7f
#define LL long long
using namespace std;
const int N=;
const int mod=; struct node
{
int key, pre, flip, ch[], son[];
}nod[N];
int n, m, a, b, node_cnt, root; int create_node(int v,int far)
{
nod[node_cnt].key=v;
nod[node_cnt].pre=far;
nod[node_cnt].flip=;
nod[node_cnt].ch[]=;
nod[node_cnt].ch[]=;
nod[node_cnt].son[]=;
nod[node_cnt].son[]=;
return node_cnt++;
} void push_down(int t)
{
if(nod[t].flip)
{
swap(nod[t].ch[], nod[t].ch[]);
swap(nod[t].son[], nod[t].son[]);
nod[t].flip=;
int L=nod[t].ch[], R=nod[t].ch[];
if(L) nod[L].flip=!nod[L].flip;
if(R) nod[R].flip=!nod[R].flip;
}
} void Rotate(int t,int d)
{
int son=nod[t].ch[d];
int far=nod[t].pre;
int gra=nod[far].pre; nod[son].pre=far;
nod[far].pre=t;
nod[t].pre=gra; nod[t].ch[d]=far;
nod[far].ch[d^]=son;
nod[gra].ch[ nod[gra].ch[]==far ]=t; nod[far].son[d^]=nod[t].son[d];
nod[t].son[d]+=nod[far].son[d]+;
} int Insert(int t,int v)
{
if(t==) return root=create_node(v, );
if( v<nod[t].key )
{
if(nod[t].ch[]) return Insert(nod[t].ch[], v);
else return nod[t].ch[]=create_node(v, t);
}
else
{
if(nod[t].ch[]) return Insert(nod[t].ch[], v);
else return nod[t].ch[]=create_node(v, t);
}
} void Splay(int t,int goal)
{
while(nod[t].pre!=goal)
{
int f=nod[t].pre, g=nod[f].pre;
if(g==goal) Rotate(t, nod[f].ch[]==t);
else
{
int d1=nod[f].ch[]==t, d2=nod[g].ch[]==f;
if(d1==d2) Rotate(f, d1),Rotate(t, d1);
else Rotate(t, d1),Rotate(t, d2);
}
}
if(!goal) root=t;
} int Find(int t,int k) //找第k个元素,必须能找到。这里不处理出错。
{
push_down(t); //找的时候顺便往下推。
if( nod[t].son[]+==k ) return t;
if( k<nod[t].son[]+ ) return Find(nod[t].ch[], k);
else return Find(nod[t].ch[], k-nod[t].son[]-);
} void Split(int t, int k, int &L, int &R) //在以t为根的树中将[1,k]分离出来,变成两棵树L和R。
{
Splay( Find(t, k), ); //查找第k个元素,并伸展到根
L=root;
R=nod[L].ch[];
nod[L].son[]=;
nod[L].ch[]=;
nod[R].pre=;
} int Merge(int L,int R)
{
int k=nod[L].son[]+nod[L].son[]+;
Splay( Find(L, k), ); //在用Splay时,必须先往下推。
L=root;
nod[L].ch[]=R;
nod[R].pre=L;
nod[L].son[]=nod[R].son[]++nod[R].son[];
return L;
} void cal(int a,int b) //从树中取出[a,b]然后旋转,插到尾部
{
int left=, mid=, right=;
if(a!= && b!=n) //三段
{
Split(root, a-, left, right);
Split(right, b-a+, mid, right );
nod[mid].flip^=;
root=Merge(Merge( left, right ) , mid );
}
else if(a==) //中后段
{
Split(root, b, mid, right );
nod[mid].flip^=;
root=Merge( right, mid );
}
else if(b==n) //前中段
{
Split(root, a-, left, mid);
nod[mid].flip^=;
root=Merge(left, mid );
}
} void print(int t) //深搜输出
{
push_down(t); //要往下推
if(nod[t].ch[]) print(nod[t].ch[]);
printf("%d\n", nod[t].key);
if(nod[t].ch[]) print(nod[t].ch[]);
} int main()
{
//freopen("input.txt", "r", stdin);
node_cnt=;root=;
cin>>n>>m;
for(int i=; i<=n; i++) Splay(Insert(root, i), ); for(int i=; i<m; i++)
{
scanf("%d%d",&a,&b);
if(a== && b==n) nod[root].flip^=; //整个区间都翻转
cal(a,b);
}
print(root);
return ;
}
AC代码
UVA 11922 Permutation Transformer (Splay树)的更多相关文章
- UVA 11922 Permutation Transformer —— splay伸展树
题意:根据m条指令改变排列1 2 3 4 … n ,每条指令(a, b)表示取出第a~b个元素,反转后添加到排列尾部 分析:用一个可分裂合并的序列来表示整个序列,截取一段可以用两次分裂一次合并实现,粘 ...
- UVa 11922 - Permutation Transformer 伸展树
第一棵伸展树,各种调试模板……TVT 对于 1 n 这种查询我处理的不太好,之前序列前后没有添加冗余节点,一直Runtime Error. 后来加上冗余节点之后又出了别的状况,因为多了 0 和 n+1 ...
- UVA - 11922 Permutation Transformer (splay)
题目链接 题意:你的任务是根据m条指令改变排列{!,2,3,...,n}.每条指令(a,b)表示取出第a~b个元素,翻转后添加到排列的尾部.输出最终序列. 解法:splay对区间分裂合并翻转,模板题. ...
- UVA 11922 Permutation Transformer(Splay Tree)
题目链接: http://acm.hust.edu.cn/vjudge/problem/viewProblem.action?id=18902 [思路] 伸展树+打标记. 用伸展树维护这个序列,使得能 ...
- UVA 11922 Permutation Transformer(平衡二叉树)
Description Write a program to transform the permutation 1, 2, 3,..., n according to m instructions. ...
- uva 11922 Permutation Transforme/splay tree
原题链接:http://acm.hust.edu.cn/vjudge/problem/viewProblem.action?id=18902 伸展树的区间翻转剪切... 如下: #include< ...
- uva 11922 - Permutation Transformer
splay的题: 学习白书上和网上的代码敲的: #include <cstdio> #include <cstring> #include <cstdlib> #i ...
- uva 12003 Array Transformer (线段树套平衡树)
http://uva.onlinejudge.org/index.php?option=com_onlinejudge&Itemid=8&page=show_problem&p ...
- UVA 11525 Permutation ——(线段树,脑筋急转弯)
只要注意到对于譬如:S1*(k-1)! 因为后面k-1个数字的全排列个数刚好是(k-1)!,那么第一个数字就是没有取过的数字的第(S1+1)个即可.取走这个数字以后这个数字就不能再用了,依次类推即可得 ...
随机推荐
- Eclipse慢慢学会的快捷键
Java编辑器 添加单个import Ctrl+Shift+M Java编辑器 组织多个import Ctrl+Shift+O Ctrl+M切换窗口的大小 Ctrl+D删除当前行 ---------- ...
- I.MX6 MAC地址修改
/*********************************************************************** * I.MX6 MAC地址修改 * 说明: * I.M ...
- AutoIt获取Gridview中可以修改列的值
有一个界面如上图:黑色框框部分是一个整体,也是一个gridview,如果我想把框框中右侧数据获取出来,该如何操作? 我尝试过了很多途径,都无法成功. 今天,我发现,当鼠标焦点在黑色框框左侧的部分的时候 ...
- Java AWT组件开发和Swing界面编程
一.AWT组件开发 1.AWT AWT是抽象窗口工具箱的缩写,它为编写图形用户界面提供了用户接口,通过这个接口就可以继承很多方法,省去了很多工作.AWT还能使应用程序更好地同用户进行交互. AWT中的 ...
- absolute 和float
position:absolute与float:left是近亲 包裹性 包裹性换种说法就是让元素inline-block化,例如一个div标签默认宽度是100%显示的,但是一旦被absolute属性缠 ...
- 文本质量巧设置,一招让Visio 2007字体从模糊到清晰
微软的Visio是一款很好用的画图工具,不过,它有一个地方不太好,就是中文字体比较模糊. 如下图: 矩形框内是宋体,9pt,字体很不清晰.无奈我就只好用雅黑字体,略微好一些. 今天发现一个设置,只有修 ...
- WebService安全解决方案—简单握手协议
具体方案如下图: 2.解决方案分析 A.SiteA每次向SiteB发送的请求参数都不一样,造成伪造者难以模仿和推敲里面的算法过程. B.伪造者获得了SayHelloRequest的数据,它向SiteB ...
- 洛谷P2219 [HAOI2007]修筑绿化带(单调队列)
传送门 啧……明明以前做到过这种类型的题结果全忘了…… 这种矩阵的,一般都是先枚举行,然后对列进行一遍单调队列,搞出右下角在每一行中合法位置时的最小权值 再枚举列,对行做一遍单调队列,用之前搞出来的最 ...
- 关于ios7 以上版本 view被导航栏遮挡的问题 解决方案
self.edgesForExtendedLayout = UIRectEdgeNone; 如果导航栏是默认带磨砂透明效果的,使用了edgesForExtendedLayout可能会出现导航栏变不透明 ...
- JS获取屏幕的大小
<html><script>function a(){document.write("屏幕分辨率为:"+screen.width+"*" ...