划分树的模板题。
1 #include <iostream> 2 #include <algorithm> 3 #include <cstdio> 4 using namespace std; 5 6 const int N = 100001; 7 int tree[20][N]; 8 int sum[20][N]; 9 int as[N]; 10 11 void build( int p, int l, int r ) 12 { 13 int mid = ( ( l + r ) >> 1 ); 14 int lm = 0, ls = l, rs = mid + 1; 15 for ( int i = mid; i >= l; i-- ) 16 { 17 if ( as[i] == as[mid] ) 18 lm++; 19 else 20 break; 21 } 22 for ( int i = l; i <= r; i++ ) 23 { 24 if ( i == l ) 25 sum[p][i] = 0; 26 else 27 sum[p][i] = sum[p][i - 1]; 28 if ( tree[p][i] == as[mid] ) 29 { 30 if ( lm ) 31 { 32 lm--; 33 sum[p][i]++; 34 tree[p + 1][ls++] = tree[p][i]; 35 } 36 else 37 { 38 tree[p + 1][rs++] = tree[p][i]; 39 } 40 } 41 else if ( tree[p][i] < as[mid] ) 42 { 43 sum[p][i]++; 44 tree[p + 1][ls++] = tree[p][i]; 45 } 46 else 47 { 48 tree[p + 1][rs++] = tree[p][i]; 49 } 50 } 51 if ( l == r ) 52 return ; 53 build( p + 1, l, mid ); 54 build( p + 1, mid + 1, r ); 55 } 56 57 int query( int p, int l, int r, int ql, int qr, int k ) 58 { 59 if ( l == r ) 60 return tree[p][l]; 61 int mid = ( ( l + r ) >> 1 ); 62 int s, ss; 63 if ( ql == l ) 64 s = 0, ss = sum[p][qr]; 65 else 66 s = sum[p][ql - 1], ss = sum[p][qr] - s; 67 if ( k <= ss ) 68 return query( p + 1, l, mid, l + s, l + sum[p][qr] - 1, k ); 69 else 70 return query( p + 1, mid + 1, r, mid + 1 - l + ql - s, mid + 1 - l + qr - sum[p][qr], k - ss ); 71 } 72 73 int main () 74 { 75 int n, m; 76 while ( scanf("%d%d", &n, &m) != EOF ) 77 { 78 for ( int i = 1; i <= n; i++ ) 79 { 80 scanf("%d", as + i); 81 tree[0][i] = as[i]; 82 } 83 sort( as + 1, as + 1 + n ); 84 build( 0, 1, n ); 85 while ( m-- ) 86 { 87 int a, b, c; 88 scanf("%d%d%d", &a, &b, &c); 89 printf("%d\n", query( 0, 1, n, a, b, c )); 90 } 91 } 92 return 0; 93 }
时间: 2024-10-12 08:06:14