UVA 11922 Permutation Transformer —— splay伸展树

Posted kiraa

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了UVA 11922 Permutation Transformer —— splay伸展树相关的知识,希望对你有一定的参考价值。

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

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

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

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

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

代码如下:

  1 #include <cstdio>
  2 #include <cstdlib>
  3 #include <iostream>
  4 #include <vector>
  5 using namespace std;
  6 
  7 struct Node {
  8     Node* ch[2];
  9     int r, v, s;
 10     int flip;
 11     Node(int vv): v(vv) {
 12         r = rand();
 13         s = 1; 
 14         ch[0] = ch[1] = NULL;
 15         flip = 0;
 16     }
 17     bool cmp(const int &x) const {
 18         if(x == v) return -1;
 19         return x < v ? 0 : 1;
 20     }
 21     void maintain() {
 22         s = 1; 
 23         if(ch[0] != NULL) s += ch[0]->s;
 24         if(ch[1] != NULL) s += ch[1]->s;
 25     }
 26     void pushdown() {
 27         if(flip) {
 28             flip = 0;
 29             swap(ch[0], ch[1]);
 30             if(ch[0] != NULL) ch[0]->flip = !ch[0]->flip;
 31             if(ch[1] != NULL) ch[1]->flip = !ch[1]->flip;
 32         }
 33     }
 34 };
 35 void rotate(Node* &o, int d) {
 36     Node* k = o->ch[d^1]; o->ch[d^1] = k->ch[d]; k->ch[d] = o;
 37     o->maintain(); k->maintain(); o = k;
 38 }
 39 void insert(Node* &o, int x) {
 40     if(o == NULL) o = new Node(x);
 41     else {
 42         int d = o->cmp(x);
 43         insert(o->ch[d], x);
 44         if(o->ch[d]->r > o->r) rotate(o, d^1);
 45     }
 46     o->maintain();
 47 }
 48 
 49 void splay(Node* &o, int k) {
 50     o->pushdown();
 51     int s = o->ch[0] == NULL ? 0 : o->ch[0]->s;
 52     int d = k <= s ? 0 : (k == s+1 ? -1 : 1);
 53     if(d == 1) k -= s+1;
 54     if(d != -1) {
 55         splay(o->ch[d], k);
 56         rotate(o, d^1);
 57     }
 58 }
 59 
 60 Node* merge(Node* left, Node* right) {
 61     splay(left, left->s);
 62     left->ch[1] = right;
 63     left->maintain();
 64     return left;
 65 }
 66 
 67 void split(Node* o, int k , Node* &left, Node* &right) {
 68     splay(o, k);
 69     left = o;
 70     right = o->ch[1];
 71     o->ch[1] = NULL;
 72     left->maintain();
 73 }
 74 vector<int> seq;
 75 void dfs(Node* o) {
 76     if(o == NULL) return;
 77     o->pushdown();
 78     dfs(o->ch[0]);
 79     if(o->v) {
 80         //printf("%d ", o->v);
 81         seq.push_back(o->v);
 82     }
 83     dfs(o->ch[1]);
 84 }
 85 int n, m;
 86 int main() {
 87     cin >> n >> m;
 88     Node* root = new Node(0); //虚拟首结点0,方便分裂操作
 89     for(int i = 1; i <= n; i++) insert(root, i);
 90     while(m--) {
 91         int a, b;
 92         cin >> a >> b;
 93         Node *left, *mid, *right, *o;
 94         split(root, a, left, o);
 95         split(o, b-a+1, mid, right);
 96         mid->flip ^= 1;
 97         root = merge(merge(left, right), mid);
 98     }
 99     dfs(root);
100     for(int i = 0; i < seq.size(); i++) cout<<seq[i]<<endl;
101     return 0;
102 }

 

以上是关于UVA 11922 Permutation Transformer —— splay伸展树的主要内容,如果未能解决你的问题,请参考以下文章

UVA 11922 Permutation Transformer —— splay伸展树

uva11922splay

Uva 11922 Splay

UVa 11922 & splay的合并与分裂

UVA - 11922 区间反转+拼接 可持久化Treap

UVA11027 Palindromic Permutation回文