fzu 1962 树状数组 OR 线段树
优雅的树状数组!人们发明了复杂度为logn的求解第k小的方法,常数小且代码量小,实在是用来求解本类题目的最佳方法,可惜的是我的Treap超时了......
树状数组:
1 #include <iostream> 2 #include <cstring> 3 #include <cstdio> 4 using namespace std; 5 6 const int N = 500001; 7 int c[N]; 8 int n, m, maxn; 9 10 int lb( int i ) 11 { 12 return i & -i; 13 } 14 15 void update( int i, int v ) 16 { 17 while ( i <= n ) 18 { 19 c[i] += v; 20 i += lb(i); 21 } 22 } 23 24 int sum( int i ) 25 { 26 int ans = 0; 27 while ( i ) 28 { 29 ans += c[i]; 30 i -= lb(i); 31 } 32 return ans; 33 } 34 35 int kth( int k ) 36 { 37 int ans = 0, cnt = 0; 38 for ( int i = 20; i >= 0; i-- ) 39 { 40 ans += ( 1 << i ); 41 if ( ans >= maxn || cnt + c[ans] >= k ) 42 { 43 ans -= ( 1 << i ); 44 } 45 else 46 { 47 cnt += c[ans]; 48 } 49 } 50 return ans + 1; 51 } 52 53 int main () 54 { 55 while ( scanf("%d%d", &n, &m) != EOF ) 56 { 57 memset( c, 0, sizeof(c) ); 58 for ( int i = 1; i <= n; i++ ) 59 { 60 update( i, 1 ); 61 } 62 maxn = n; 63 while ( m-- ) 64 { 65 char op[2]; 66 int num; 67 scanf("%s%d", op, &num); 68 if ( op[0] == 'L' ) 69 { 70 int kk = kth(num); 71 update( kk, -1 ); 72 } 73 else if ( op[0] == 'R' ) 74 { 75 if ( sum(num) == sum( num - 1 ) ) 76 { 77 update( num, 1 ); 78 } 79 } 80 else if ( op[0] == 'Q' ) 81 { 82 int kk = kth(num); 83 printf("%d\n", kk); 84 } 85 } 86 } 87 return 0; 88 }
线段树当然也可以做:
1 #include <iostream> 2 #include <cstring> 3 #include <cstdio> 4 using namespace std; 5 6 const int N = 500001; 7 int n, m; 8 9 struct Node 10 { 11 int l, r, sum; 12 } node[N << 2]; 13 14 void pushup( int i ) 15 { 16 node[i].sum = node[i << 1].sum + node[i << 1 | 1].sum; 17 } 18 19 void build( int i, int l, int r ) 20 { 21 node[i].l = l, node[i].r = r, node[i].sum = node[i].r - node[i].l + 1; 22 if ( l == r ) return ; 23 int mid = ( l + r ) >> 1; 24 build( i << 1, l, mid ); 25 build( i << 1 | 1, mid + 1, r ); 26 } 27 28 void update( int i, int pos, int val ) 29 { 30 if ( node[i].l == pos && node[i].r == pos ) 31 { 32 node[i].sum = val; 33 return ; 34 } 35 int mid = ( node[i].l + node[i].r ) >> 1; 36 if ( pos <= mid ) 37 { 38 update( i << 1, pos, val ); 39 } 40 else 41 { 42 update( i << 1 | 1, pos, val ); 43 } 44 pushup(i); 45 } 46 47 int query( int i, int v ) 48 { 49 if ( node[i].l == node[i].r ) return node[i].l; 50 if ( node[i << 1].sum >= v ) return query( i << 1, v ); 51 return query( i << 1 | 1, v - node[i << 1].sum ); 52 } 53 54 int main () 55 { 56 while ( scanf("%d%d", &n, &m) != EOF ) 57 { 58 build( 1, 1, n ); 59 scanf("%d", &m); 60 while ( m-- ) 61 { 62 char op[2]; 63 int x; 64 scanf("%s %d", op, &x); 65 if ( op[0] == 'L' ) 66 { 67 int kk = query( 1, x ); 68 update( 1, kk, 0 ); 69 } 70 else if ( op[0] == 'R' ) 71 { 72 update( 1, x, 1 ); 73 } 74 else if ( op[0] == 'Q' ) 75 { 76 int kk = query( 1, x ); 77 printf("%d\n", kk); 78 } 79 } 80 } 81 return 0; 82 }