splay第一题,有了Treap的基础以后感觉splay还是比较好理解的,splay的优势在于编程复杂度比较低且效率不错,通过splay操作以及衍生的split和merge操作可以实现很强大的功能。
1 #include <iostream> 2 #include <cstring> 3 #include <cstdio> 4 using namespace std; 5 6 struct Node 7 { 8 Node * ch[2]; 9 int val; 10 int rank; 11 int sz; 12 int flip; 13 14 int cmp( int x ) const 15 { 16 if ( x == rank ) return -1; 17 return x < rank ? 0 : 1; 18 } 19 20 void maintain() 21 { 22 sz = rank = 1; 23 if ( ch[0] != NULL ) 24 { 25 sz += ch[0]->sz; 26 rank += ch[0]->sz; 27 } 28 if ( ch[1] != NULL ) 29 { 30 sz += ch[1]->sz; 31 } 32 } 33 34 void pushdown() 35 { 36 if ( flip ) 37 { 38 swap( ch[0], ch[1] ); 39 flip = 0; 40 if ( ch[0] != NULL ) ch[0]->flip ^= 1; 41 if ( ch[1] != NULL ) ch[1]->flip ^= 1; 42 } 43 } 44 }; 45 46 bool ok( int val ) 47 { 48 return val != 0; 49 } 50 51 void inorder( Node * o ) 52 { 53 if ( o == NULL ) return ; 54 o->pushdown(); 55 inorder( o->ch[0] ); 56 if ( ok( o->val ) ) printf("%d\n", o->val); 57 inorder( o->ch[1] ); 58 } 59 60 void rotate( Node * & o, int d ) 61 { 62 Node * k = o->ch[d ^ 1]; 63 o->ch[d ^ 1] = k->ch[d]; 64 k->ch[d] = o; 65 o->maintain(); 66 k->maintain(); 67 o = k; 68 } 69 70 void splay( Node * & o, int k ) 71 { 72 o->pushdown(); 73 o->maintain(); 74 int d = o->cmp(k); 75 if ( d != -1 ) 76 { 77 if ( d == 1 ) k -= o->rank; 78 Node * p = o->ch[d]; 79 p->pushdown(); 80 p->maintain(); 81 int d2 = p->cmp(k); 82 if ( d2 != -1 ) 83 { 84 int k2 = ( d2 == 0 ? k : k - p->rank ); 85 splay( p->ch[d2], k2 ); 86 if ( d == d2 ) 87 { 88 rotate( o, d ^ 1 ); 89 } 90 else 91 { 92 rotate( o->ch[d], d ); 93 } 94 } 95 rotate( o, d ^ 1 ); 96 } 97 } 98 99 Node * build( int l, int r ) 100 { 101 if ( l > r ) return NULL; 102 Node * o = new Node(); 103 int mid = ( l + r ) >> 1; 104 o->sz = r - l + 1; 105 o->val = mid; 106 o->rank = mid - l + 1; 107 o->flip = 0; 108 o->ch[0] = build( l, mid - 1 ); 109 o->ch[1] = build( mid + 1, r ); 110 return o; 111 } 112 113 void split( Node * o, int k, Node * & left, Node * & right ) 114 { 115 splay( o, k ); 116 left = o; 117 right = o->ch[1]; 118 o->ch[1] = NULL; 119 left->maintain(); 120 } 121 122 Node * merge( Node * left, Node * right ) 123 { 124 splay( left, left->sz ); 125 left->ch[1] = right; 126 left->maintain(); 127 return left; 128 } 129 130 int main () 131 { 132 int n, m; 133 while ( scanf("%d%d", &n, &m) != EOF ) 134 { 135 Node * root = build( 0, n ); 136 while ( m-- ) 137 { 138 int a, b; 139 scanf("%d%d", &a, &b); 140 Node * left, * mid, * right, * o; 141 split( root, a, left, o ); 142 split( o, b - a + 1, mid, right ); 143 mid->flip ^= 1; 144 root = merge( merge( left, right ), mid ); 145 } 146 inorder(root); 147 } 148 return 0; 149 }