优雅的树状数组!人们发明了复杂度为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 }
时间: 2024-10-10 17:25:03