UVA 11922 Permutation Transformer(平衡二叉树)

Description

Write a program to transform the permutation 1, 2, 3,..., n according to m instructions. Each instruction (ab) means to take out the subsequence from the a-th to the b-th element, reverse it, then append it to the end.

Input

There is only one case for this problem. The first line contains two integers n and m ( 1$ \le$nm$ \le$100, 000). Each of the next m lines contains an instruction consisting of two integers a and b ( 1$ \le$a$ \le$b$ \le$n).

Output

Print n lines, one for each integer, the final permutation.

Explanation of the sample below

Instruction (2,5): Take out the subsequence {2,3,4,5}, reverse it to {5,4,3,2}, append it to the remaining permutation {1,6,7,8,9,10}

Instruction (4,8): The subsequence from the 4-th to the 8-th element of {1,6,7,8,9,10,5,4,3,2} is {8,9,10,5,4}. Take it out, reverse it, and you'll get the sample output.

 

题目大意:有一个1~n的序列,每次取出序列中第a~b的序列,翻转后排在序列的最后,求最后形成的序列

思路:用伸展树维护,先把1~a-1分裂出来,再把a~b分裂出来,翻转,然后接在最后。至于怎么翻转,标记一下就可以了。

PS:标记完翻转之后我脑子抽了一下每次都把标记传到最下面结果毫无疑问是TLE了……

 

  1 #include<cstdio>
  2 #include<cstring>
  3 #include<algorithm>
  4 using namespace std;
  5 
  6 const int MAXN = 100010;
  7 
  8 int child[MAXN][2], fa[MAXN], size[MAXN];
  9 bool flip[MAXN];
 10 
 11 inline void update(int &x) {
 12     size[x] = size[child[x][0]] + size[child[x][1]] + 1;
 13 }
 14 
 15 inline void pushdown(int &x) {
 16     if(flip[x]) {
 17         flip[x] = 0;
 18         swap(child[x][0], child[x][1]);
 19         flip[child[x][0]] ^= 1;
 20         flip[child[x][1]] ^= 1;
 21     }
 22 }
 23 
 24 inline void rotate(int &x, int t) {
 25     int y = child[x][t];
 26     child[x][t] = child[y][t ^ 1];
 27     child[y][t ^ 1] = x;
 28     update(x); update(y);
 29     x = y;
 30 }
 31 
 32 //rotate the kth to root
 33 void splay(int &x, int k) {
 34     pushdown(x);
 35     if(k == size[child[x][0]] + 1) return ;
 36     int t = (k > size[child[x][0]] ? 1 : 0);
 37     if(t == 1) k -= (size[child[x][0]] + 1);
 38     int p = child[x][t];
 39     pushdown(p);
 40     int t2 = (k > size[child[p][0]] ? 1 : 0);
 41     int k2 = (t2 == 0 ? k : k - size[child[p][0]] - 1);
 42     if(k != size[child[p][0]] + 1) {
 43         splay(child[p][t2], k2);
 44         if(t == t2) rotate(x, t);
 45         else rotate(child[x][t], t ^ 1);
 46     }
 47     rotate(x, t);
 48 }
 49 //left cannot be null
 50 inline int merge(int left, int right) {
 51     splay(left, size[left]);
 52     child[left][1] = right;
 53     update(left);
 54     return left;
 55 }
 56 
 57 inline void split(int x, int k, int &left, int &right) {
 58     splay(x, k);
 59     left = x;
 60     right = child[x][1];
 61     child[x][1] = 0;
 62     update(left);
 63 }
 64 
 65 void print(int x) {
 66     if(x == 0) return ;
 67     pushdown(x);
 68     print(child[x][0]);
 69     if(x != 1) printf("%d\n", x - 1);
 70     print(child[x][1]);
 71 }
 72 
 73 int cnt;
 74 
 75 int build(int l, int r) {
 76     if(l > r) return 0;
 77     int mid = (l + r) >> 1;
 78     child[mid][0] = build(l, mid - 1);
 79     child[mid][1] = build(mid + 1, r);
 80     update(mid);
 81     return mid;
 82 }
 83 
 84 int root;
 85 
 86 int main() {
 87     int n, m, a, b;
 88     scanf("%d%d", &n, &m);
 89     root = build(1, n + 1);
 90     while(m--) {
 91         scanf("%d%d", &a, &b);
 92         int left, mid, right, x;
 93         split(root, a, left, x);
 94         split(x, b - a + 1, mid, right);
 95         flip[mid] ^= 1;
 96         root = merge(merge(left, right), mid);
 97         //print(root); system("pause");
 98     }
 99     print(root);
100 }
View Code

 

posted @ 2013-07-27 18:27  Oyking  阅读(421)  评论(0编辑  收藏  举报