UVa 11922 - Permutation Transformer 伸展树

第一棵伸展树,各种调试模板……TVT

对于 1 n 这种查询我处理的不太好,之前序列前后没有添加冗余节点,一直Runtime Error。

后来加上冗余节点之后又出了别的状况,因为多了 0 和 n+1 这两个节点,并且每次截取翻转添加到序列最后,因此无法确定 n+1 这个节点在序列的哪个位置。

比如(括号中的为添加的冗余节点):

(0) 1 2 3 4 5 (6)

我把[3,4]截取翻转添加到序列尾部,会变成这样:

(0)1 2 5 (6)4 3

此时我如果再希望截取[3,4],期望的结果应该是:

1 2 3 4 5

而实际上会变成:

(0)1 2 4 3 (6) 5

我用了一种挺麻烦的方式解决的这个问题:

就是让伸展树在冗余节点n+1之前的位置再分裂一次,每次把截取的序列添加到节点n+1的前面,一直维持n+1在序列最末尾,这样就不会有干扰了。

 

  1 #include <cstdio>
  2 #include <cstring>
  3 #include <cstdlib>
  4 #include <algorithm>
  5 
  6 using namespace std;
  7 
  8 struct Node
  9 {
 10     Node *ch[2];
 11     int v, s;
 12     int flip;
 13     Node( int v ):v(v)
 14     {
 15         ch[0] = ch[1] = NULL;
 16         s = 1;
 17         flip = 0;
 18     }
 19     int cmp( int x ) const
 20     {
 21         int t = ( ch[0] == NULL ) ? 0 : ch[0]->s;
 22         if ( t >= x ) return 0;
 23         if ( t + 1 == x ) return -1;
 24         return 1;
 25     }
 26     void maintain()
 27     {
 28         s = 1;
 29         if ( ch[0] != NULL ) s += ch[0]->s;
 30         if ( ch[1] != NULL ) s += ch[1]->s;
 31         return;
 32     }
 33     void pushDown()
 34     {
 35         if ( flip )
 36         {
 37             flip = 0;
 38             swap( ch[0], ch[1] );
 39             if ( ch[0] != NULL ) ch[0]->flip = !ch[0]->flip;
 40             if ( ch[1] != NULL ) ch[1]->flip = !ch[1]->flip;
 41         }
 42     }
 43 };
 44 
 45 int n, m;
 46 
 47 void Rotate( Node* &o, int d )   //d=0 左旋  d=1 右旋
 48 {
 49     Node *k = o->ch[ d ^ 1 ];
 50     o->ch[ d ^ 1 ] = k->ch[d];
 51     k->ch[d] = o;
 52     o = k;
 53     o->ch[d]->maintain();
 54     o->maintain();
 55     return;
 56 }
 57 
 58 void splay( Node* &o, int k )
 59 {
 60     o->pushDown();
 61     int d = o->cmp(k);
 62     if ( d == 1 )
 63     {
 64         if ( o->ch[0] != NULL )
 65             k -= o->ch[0]->s;
 66         --k;
 67     }
 68     if ( d != -1 )
 69     {
 70         Node *p = o->ch[d];
 71         p->pushDown();
 72         int d2 = p->cmp(k);
 73         int k2 = k;
 74         if ( d2 == 1 )
 75         {
 76             if ( p->ch[0] != NULL )
 77                 k2 -= p->ch[0]->s;
 78             --k2;
 79         }
 80         if ( d2 != -1 )
 81         {
 82             splay( p->ch[d2], k2 );
 83             if ( d == d2 ) Rotate( o, d ^ 1 );
 84             else Rotate( o->ch[d], d );
 85         }
 86         Rotate( o, d ^ 1 );
 87     }
 88     return;
 89 }
 90 
 91 Node *Merge( Node *left, Node *right )
 92 {
 93     splay( left, left->s );
 94     left->ch[1] = right;
 95     left->maintain();
 96     return left;
 97 }
 98 
 99 void Split( Node *o, int k, Node* &left, Node* &right )
100 {
101     splay( o, k );
102     left = o;
103     right = o->ch[1];
104     o->ch[1] = NULL;
105     left->maintain();
106     return;
107 }
108 
109 void build( Node* &o, int l, int r )
110 {
111     int m = ( l + r ) >> 1;
112     o = new Node(m);
113     if ( l < m ) build( o->ch[0], l, m - 1 );
114     if ( r > m ) build( o->ch[1], m + 1, r );
115     o->maintain();
116     return;
117 }
118 
119 void DFS( Node *cur )
120 {
121     cur->pushDown();
122     if ( cur->ch[0] ) DFS( cur->ch[0] );
123     if ( cur->v && cur->v != n + 1 ) printf( "%d\n", cur->v );
124     if ( cur->ch[1] ) DFS( cur->ch[1] );
125     return;
126 }
127 
128 void DeleteTree( Node *cur )
129 {
130     if ( cur->ch[0] ) DeleteTree( cur->ch[0] );
131     if ( cur->ch[1] ) DeleteTree( cur->ch[1] );
132     delete cur;
133     return;
134 }
135 
136 Node *root;
137 
138 int main()
139 {
140     while ( ~scanf( "%d%d", &n, &m ) )
141     {
142         root = NULL;
143         build( root, 0, n + 1 );  //前后各加了一个冗余节点
144         while ( m-- )
145         {
146             int a, b;
147             scanf( "%d%d", &a, &b );
148             Node *left, *mid, *right, *o, *tmp;
149 
150             Split( root, a, left, o );
151             Split( o, b - a + 1, mid, right );
152 
153             if ( right->s - 1 > 0 )
154             {
155                 Split( right, right->s - 1, tmp, o );
156                 mid->flip ^= 1;
157                 root = Merge( left, Merge( Merge( tmp, mid ), o ) );
158             }
159             else
160             {
161                 mid->flip ^= 1;
162                 root = Merge( left, Merge( mid, right ) );
163             }
164         }
165         DFS( root );
166         DeleteTree( root );
167     }
168     return 0;
169 }

 

posted @ 2013-07-17 11:26  冰鸮  阅读(310)  评论(0编辑  收藏  举报