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 }

 

你可能感兴趣的:(transform)