题意:给定一个数列,求一个区间的第K大数
模板题, 其中的newl, newr 有点不明白.
1 #include <iostream> 2 #include <algorithm> 3 using namespace std; 4 const int M = 100005; 5 int toLeft[20][M], tree[20][M], sorted[M]; 6 7 void build(int level, int left, int right) 8 { 9 if (left == right) return; 10 int i, mid = (left + right) >>1; 11 int suppose = mid - left + 1; 12 for (i=left; i<=right; i++) 13 if (tree[level][i] < sorted[mid]) 14 suppose--; 15 int lpos = left, rpos = mid+1; 16 for (i=left; i<=right; i++) 17 { 18 if (i == left) 19 toLeft[level][i] = 0; 20 else 21 toLeft[level][i] = toLeft[level][i-1]; 22 if (tree[level][i] < sorted[mid]) 23 { 24 toLeft[level][i]++; 25 tree[level+1][lpos++] = tree[level][i]; 26 } 27 else if (tree[level][i] > sorted[mid]) 28 { 29 tree[level+1][rpos++] = tree[level][i]; 30 } 31 else 32 { 33 if (suppose != 0) 34 { 35 suppose--; 36 toLeft[level][i]++; 37 tree[level+1][lpos++] = tree[level][i]; 38 } 39 else 40 tree[level+1][rpos++] = tree[level][i]; 41 } 42 } 43 build(level+1, left, mid); 44 build(level+1, mid+1, right); 45 } 46 47 int query(int level, int left, int right, int qleft, int qright, int k) 48 { 49 if (qleft == qright) 50 return tree[level][qright]; 51 int s, ss, mid = (left + right)>>1; 52 if (left == qleft) 53 { 54 s = 0; 55 ss = toLeft[level][qright]; 56 } 57 else 58 { 59 s = toLeft[level][qleft-1]; 60 ss = toLeft[level][qright] - s; 61 } 62 int newl, newr; 63 if (k <= ss) 64 { 65 newl = left + s; 66 newr = left + s + ss -1; 67 return query(level+1, left, mid, newl, newr, k); 68 } 69 else 70 { 71 newl = mid-left+1+qleft-s; 72 newr = mid-left+1+qright-s-ss; 73 return query(level+1, mid+1, right, newl, newr, k-ss); 74 } 75 } 76 77 int main() 78 { 79 int n, m; 80 int i; 81 while (scanf("%d%d", &n, &m) == 2) 82 { 83 for (i=1; i<=n; i++) 84 { 85 scanf("%d", &tree[0][i]); 86 sorted[i] = tree[0][i]; 87 } 88 sort(sorted+1, sorted+n+1); 89 build(0,1,n); 90 int ql, qr, k; 91 for (i=0; i<m; i++) 92 { 93 scanf("%d%d%d", &ql, &qr, &k); 94 printf("%d\n", query(0, 1, n, ql, qr, k)); 95 } 96 } 97 return 0; 98 }