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 }