题意:根据m条指令改变排列1 2 3 4 … n ,每条指令(a, b)表示取出第a~b个元素,反转后添加到排列尾部

分析:用一个可分裂合并的序列来表示整个序列,截取一段可以用两次分裂一次合并实现,粘贴到末尾可以用一次合并实现。

翻转可以采用在每个结点上做标记的方法,flip = 1意味着将这棵子树翻转,可以类似线段树用一个pushdown()实现标记向下传递。

可以发现当前排列就是伸展树的中序遍历序列。中序遍历打印结果即可。

注意代码中设置了虚拟首结点0的技巧。

代码如下:

 #include <cstdio>
#include <cstdlib>
#include <iostream>
#include <vector>
using namespace std; struct Node {
Node* ch[];
int r, v, s;
int flip;
Node(int vv): v(vv) {
r = rand();
s = ;
ch[] = ch[] = NULL;
flip = ;
}
bool cmp(const int &x) const {
if(x == v) return -;
return x < v ? : ;
}
void maintain() {
s = ;
if(ch[] != NULL) s += ch[]->s;
if(ch[] != NULL) s += ch[]->s;
}
void pushdown() {
if(flip) {
flip = ;
swap(ch[], ch[]);
if(ch[] != NULL) ch[]->flip = !ch[]->flip;
if(ch[] != NULL) ch[]->flip = !ch[]->flip;
}
}
};
void rotate(Node* &o, int d) {
Node* k = o->ch[d^]; o->ch[d^] = k->ch[d]; k->ch[d] = o;
o->maintain(); k->maintain(); o = k;
}
void insert(Node* &o, int x) {
if(o == NULL) o = new Node(x);
else {
int d = o->cmp(x);
insert(o->ch[d], x);
if(o->ch[d]->r > o->r) rotate(o, d^);
}
o->maintain();
} void splay(Node* &o, int k) {
o->pushdown();
int s = o->ch[] == NULL ? : o->ch[]->s;
int d = k <= s ? : (k == s+ ? - : );
if(d == ) k -= s+;
if(d != -) {
splay(o->ch[d], k);
rotate(o, d^);
}
} Node* merge(Node* left, Node* right) {
splay(left, left->s);
left->ch[] = right;
left->maintain();
return left;
} void split(Node* o, int k , Node* &left, Node* &right) {
splay(o, k);
left = o;
right = o->ch[];
o->ch[] = NULL;
left->maintain();
}
vector<int> seq;
void dfs(Node* o) {
if(o == NULL) return;
o->pushdown();
dfs(o->ch[]);
if(o->v) {
//printf("%d ", o->v);
seq.push_back(o->v);
}
dfs(o->ch[]);
}
int n, m;
int main() {
cin >> n >> m;
Node* root = new Node(); //虚拟首结点0,方便分裂操作
for(int i = ; i <= n; i++) insert(root, i);
while(m--) {
int a, b;
cin >> a >> b;
Node *left, *mid, *right, *o;
split(root, a, left, o);
split(o, b-a+, mid, right);
mid->flip ^= ;
root = merge(merge(left, right), mid);
}
dfs(root);
for(int i = 0; i < seq.size(); i++) cout<<seq[i]<<endl;
return ;
}

UVA 11922 Permutation Transformer —— splay伸展树的更多相关文章

  1. UVA - 11922 Permutation Transformer (splay)

    题目链接 题意:你的任务是根据m条指令改变排列{!,2,3,...,n}.每条指令(a,b)表示取出第a~b个元素,翻转后添加到排列的尾部.输出最终序列. 解法:splay对区间分裂合并翻转,模板题. ...

  2. UVa 11922 - Permutation Transformer 伸展树

    第一棵伸展树,各种调试模板……TVT 对于 1 n 这种查询我处理的不太好,之前序列前后没有添加冗余节点,一直Runtime Error. 后来加上冗余节点之后又出了别的状况,因为多了 0 和 n+1 ...

  3. UVA 11922 Permutation Transformer(Splay Tree)

    题目链接: http://acm.hust.edu.cn/vjudge/problem/viewProblem.action?id=18902 [思路] 伸展树+打标记. 用伸展树维护这个序列,使得能 ...

  4. UVA 11922 Permutation Transformer(平衡二叉树)

    Description Write a program to transform the permutation 1, 2, 3,..., n according to m instructions. ...

  5. uva 11922 Permutation Transforme/splay tree

    原题链接:http://acm.hust.edu.cn/vjudge/problem/viewProblem.action?id=18902 伸展树的区间翻转剪切... 如下: #include< ...

  6. UVA 11922 Permutation Transformer (Splay树)

    题意: 给一个序列,是从1~n共n个的自然数,接下来又m个区间,对于每个区间[a,b],从第a个到第b个从序列中分离出来,翻转后接到尾部.输出最后的序列. 思路: 这次添加了Split和Merge两个 ...

  7. uva 11922 - Permutation Transformer

    splay的题: 学习白书上和网上的代码敲的: #include <cstdio> #include <cstring> #include <cstdlib> #i ...

  8. Splay伸展树学习笔记

    Splay伸展树 有篇Splay入门必看文章 —— CSDN链接 经典引文 空间效率:O(n) 时间效率:O(log n)插入.查找.删除 创造者:Daniel Sleator 和 Robert Ta ...

  9. 【学时总结】◆学时·VI◆ SPLAY伸展树

    ◆学时·VI◆ SPLAY伸展树 平衡树之多,学之不尽也…… ◇算法概述 二叉排序树的一种,自动平衡,由 Tarjan 提出并实现.得名于特有的 Splay 操作. Splay操作:将节点u通过单旋. ...

随机推荐

  1. Spring Boot 数据库连接池参数

    挑战A.I.,赢百万奖金......了解更多详情>>> Tomcat JDBC 连接池 Spring Boot 默认选择 Tomcat JDBC Pool 作为数据库连接池.Tomc ...

  2. python 正则表达式常用操作符

  3. GBRT(GBDT)(MART)(Tree Net)(Tree link)

    源于博客 GBRT(梯度提升回归树)有好多名字,标题全是它的别名. 它是一种迭代的回归树算法,由多棵回归树组成,所有树的结论累加起来得到最终结果.在被提出之初与SVM一起被认为是泛化能力较强的算法. ...

  4. python中函数和方法区别,以及如何给python类动态绑定方法和属性(涉及types.MethodType()和__slots__)

    网上有很多同义但不同方式的说法,下面的这个说法比较让你容易理解和接受 与类和实例无绑定关系的function都属于函数(function): 与类和实例有绑定关系的function都属于方法(meth ...

  5. golang的变量

    (1)只声明:var 变量名字 类型              var a int             var a, b, c,d int      只有类型,如果初始化表达式被省略,那么将用零值 ...

  6. golang进制

  7. 一个基于Asterisk构建的VOIP应用软件:Elastix介绍

    Elastix 是一种应用软件,它整合了适用于那些基于 Asterisk 的 PBX 的最好工具,并将它们集成为单一的.易用的接口.同时,它增加了自己的工具集,以及允许创建第三方模块来使 Elasti ...

  8. 2019-8-30-C#-从零开始写-SharpDx-应用-笔刷

    title author date CreateTime categories C# 从零开始写 SharpDx 应用 笔刷 lindexi 2019-8-30 8:50:0 +0800 2019-6 ...

  9. 开发者总结的WatchKit App提交技巧

    苹果4月初宣布所有注册开发者已经可以向App Store提交基于WatchKit开发的Apple Watch app了,不过不少开发者遇到了模拟器中没有发现的问题.这篇文章主要收集了一些提交tips和 ...

  10. Java练习 SDUT-2749_区域内点的个数

    区域内点的个数 Time Limit: 1000 ms Memory Limit: 65536 KiB Problem Description X晚上睡不着的时候不喜欢玩手机,也不喜欢打游戏,他喜欢数 ...