Description
Input
Output
题目大意:给一串数字,多次询问区间的第k小值
思路:划分树模板题。关于划分树:http://www.cppblog.com/MatoNo1/archive/2011/06/27/149604.aspx
1 #include <cstdio> 2 #include <algorithm> 3 using namespace std; 4 5 #define MAXN 100005 6 int a[MAXN], a_sort[MAXN]; 7 int n, m; 8 int sum[20][MAXN]; 9 int tree[20][MAXN]; 10 11 void build(int l, int r, int dep) { 12 int i, mid = (l + r) >> 1, sum_mid = mid - l + 1, lp = l, rp = mid + 1; 13 for(int i = mid - 1; i >= l; --i) 14 if(a_sort[i] < a_sort[mid]) {sum_mid = mid - i; break;} 15 for(i = l; i <= r; ++i) { 16 sum[dep][i] = (i == l ? 0 : sum[dep][i - 1]); 17 if (tree[dep][i] < a_sort[mid]){ 18 ++sum[dep][i]; 19 tree[dep + 1][lp++] = tree[dep][i]; 20 } else if(tree[dep][i] == a_sort[mid] && sum_mid) { 21 --sum_mid; 22 ++sum[dep][i]; 23 tree[dep + 1][lp++] = tree[dep][i]; 24 } else tree[dep + 1][rp++] = tree[dep][i]; 25 } 26 if (l == r)return; 27 build(l, mid, dep + 1); 28 build(mid + 1, r, dep + 1); 29 } 30 31 int query(int l, int r, int s, int t, int k, int dep) { 32 if(l == r) return tree[dep][l]; 33 int mid = (l + r) >> 1; 34 int sum1 = (l == s ? 0 : sum[dep][s - 1]), sum2 = sum[dep][t] - sum1; 35 if(k <= sum2) return query(l, mid, l + sum1, l + sum1 + sum2 - 1, k, dep + 1); 36 else return query(mid + 1, r, mid + s - l + 1 - sum1, mid + t - l + 1 - sum1 - sum2, k - sum2, dep + 1); 37 } 38 39 int main(){ 40 int s, t, k; 41 while(scanf("%d%d", &n, &m) != EOF){ 42 for(int i = 1; i <= n; ++i){ 43 scanf("%d", &a[i]); 44 tree[0][i] = a_sort[i] = a[i]; 45 } 46 sort(a_sort + 1, a_sort + 1 + n); 47 build(1, n, 0); 48 while(m--){ 49 scanf("%d%d%d", &s, &t, &k); 50 printf("%d\n", query(1, n, s, t, k, 0)); 51 } 52 } 53 return 0; 54 }