bzoj1503 Splay 维护名次数,支持删除
题目:http://www.lydsy.com/JudgeOnline/problem.php?id=1503
题解:
维护一颗Splay和一个外部变量,树中每个节点表示一个人,节点权值a + 外部变量delta = 该员工工资。
细节看代码。
注意:一进来工资就低于最低工资的人不能算是“离开公司”的人。
1 #include <cstdio> 2 #define fprintf(...) 3 #define maxn 100100 4 5 struct Splay { 6 int key[maxn], pre[maxn], son[maxn][2], siz[maxn], ntot, root; 7 int trash[maxn], rtot; 8 9 Splay():ntot(0),root(0),rtot(0){} 10 void update( int nd ) { 11 siz[nd] = siz[son[nd][0]] + siz[son[nd][1]] + 1; 12 } 13 void rotate( int nd, int d ) { 14 int p = pre[nd]; 15 int s = son[nd][!d]; 16 int ss = son[s][d]; 17 18 if( p ) son[p][ nd==son[p][1] ] = s; 19 else root = s; 20 son[nd][!d] = ss; 21 son[s][d] = nd; 22 23 if( ss ) pre[ss] = nd; 24 pre[nd] = s; 25 pre[s] = p; 26 27 update( nd ); 28 update( s ); 29 } 30 void splay( int nd, int top=0 ) { 31 while( pre[nd]!=top ) { 32 int p = pre[nd]; 33 int nl = nd==son[p][0]; 34 if( pre[p]==top ) { 35 rotate( p, nl ); 36 } else { 37 int pp = pre[p]; 38 int pl = p==son[pp][0]; 39 if( nl==pl ) { 40 rotate( pp, pl ); 41 rotate( p, nl ); 42 } else { 43 rotate( p, nl ); 44 rotate( pp, pl ); 45 } 46 } 47 } 48 } 49 int newnode( int k, int p ) { 50 int nd; 51 if( rtot ) nd = trash[rtot--]; 52 else nd = ++ntot; 53 key[nd] = k; 54 pre[nd] = p; 55 son[nd][0] = son[nd][1] = 0; 56 siz[nd] = 1; 57 return nd; 58 } 59 void insert( int k ) { 60 fprintf( stderr, "insert(%d)\n", k ); 61 if( !root ) { 62 root = newnode( k, 0 ); 63 return; 64 } 65 int nd = root; 66 while( son[nd][ k<key[nd] ] ) 67 nd = son[nd][ k<key[nd] ]; 68 son[nd][ k<key[nd] ] = newnode( k, nd ); 69 update( nd ); 70 splay( nd, 0 ); 71 } 72 void erase_subtree( int nd ) { 73 fprintf( stderr, "erase_subtree(%d)\n", nd ); 74 if( !nd ) return; 75 erase_subtree( son[nd][0] ); 76 erase_subtree( son[nd][1] ); 77 trash[++rtot] = nd; 78 } 79 void erase( int k ) { 80 fprintf( stderr, "erase(%d)\n", k ); 81 int nd = root; 82 int active = nd; 83 while( nd ) { 84 if( key[nd]<=k ) { 85 int p = pre[nd]; 86 int ls= son[nd][0]; 87 88 if( p ) son[p][ nd==son[p][1] ] = son[nd][0]; 89 else root = son[nd][0]; 90 pre[son[nd][0]] = p; 91 92 pre[nd] = 0; 93 son[nd][0] = 0; 94 95 erase_subtree( nd ); 96 97 if( p ) update( p ); 98 nd = ls; 99 } else { 100 active = nd; 101 nd = son[nd][1]; 102 } 103 } 104 splay(active); 105 } 106 int nth( int n ) { 107 fprintf( stderr, "nth(%d)\n", n ); 108 int nd = root; 109 while(1) { 110 int ls = siz[son[nd][0]]; 111 if( n<=ls ) { 112 nd=son[nd][0]; 113 } else if( n>=ls+2 ) { 114 nd=son[nd][1]; 115 n -= ls+1; 116 } else 117 break; 118 } 119 splay( nd ); 120 return key[nd]; 121 } 122 void print( int nd ) { 123 if(!nd) return; 124 print( son[nd][0] ); 125 fprintf( stderr, "%d %d %d %d %d\n", nd, pre[nd], son[nd][0], son[nd][1], 126 key[nd] ); 127 print( son[nd][1] ); 128 } 129 }; 130 131 Splay T; 132 int n, delta, limit, cnt; 133 134 int main() { 135 //freopen( "input", "r", stdin ); 136 scanf( "%d%d", &n, &limit ); 137 delta = 0; 138 cnt = 0; 139 while(n--) { 140 char ch[2]; 141 int k; 142 scanf( "%s%d", ch, &k ); 143 switch(ch[0]) { 144 case 'I': 145 if( k<limit ) break; 146 cnt++; 147 k -= delta; 148 T.insert( k ); 149 break; 150 case 'A': 151 delta += k; 152 break; 153 case 'S': 154 delta -= k; 155 T.erase( limit-delta-1 ); 156 break; 157 case 'F': 158 if( !(1<=k && k<=T.siz[T.root]) ) printf( "-1\n" ); 159 else printf( "%d\n", T.nth(k)+delta ); 160 break; 161 } 162 fprintf( stderr, "delta=%d\n", delta ); 163 //T.print( T.root ); 164 fprintf( stderr, "\n" ); 165 } 166 printf( "%d\n", cnt-T.siz[T.root] ); 167 }