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)
", 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)
", 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)
", 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 );
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
", 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
" );
159                 else printf( "%d
", T.nth(k)+delta );
160                 break;
161         }
162         fprintf( stderr, "delta=%d
", delta );
163         //T.print( T.root );
164         fprintf( stderr, "
" );
165     }
166     printf( "%d
", cnt-T.siz[T.root] );
167 }
View Code
原文地址:https://www.cnblogs.com/idy002/p/4273608.html