划分树求第K大数

来源:互联网 发布:acg和sia知乎 编辑:程序博客网 时间:2024/06/16 10:56
输入//1 5 4 8 7   3(第三大)输出//5#include <iostream>#include <cstdio>#include <algorithm>using namespace std;int ans; #define N 100005int a[N], as[N];int n, m;int sum[20][N];int tree[20][N];void build(int c, int l, int r){    int i, mid = (l + r) >> 1, lm = mid - l + 1, lp = l, rp = mid + 1;    for (i = l; i <= mid; i++){        if (as[i] < as[mid]){            lm--;        }    }    for (i = l; i <= r; i++){        if (i == l){            sum[c][i] = 0;        }else{            sum[c][i] = sum[c][i - 1];        }        if (tree[c][i] == as[mid]){            if (lm){                lm--;                sum[c][i]++;                tree[c + 1][lp++] = tree[c][i];            }else                tree[c + 1][rp++] = tree[c][i];        } else if (tree[c][i] < as[mid]){            sum[c][i]++;            tree[c + 1][lp++] = tree[c][i];        } else{            tree[c + 1][rp++] = tree[c][i];        }    }    if (l == r)return;    build(c + 1, l, mid);    build(c + 1, mid + 1, r);}int query(int c, int l, int r, int ql, int qr, int k){    int s;    int ss;    int mid = (l + r) >> 1;    if (l == r){    ans=tree[c][l];        return ans;    }    if (l == ql){    s = 0;    ss = sum[c][qr];    }else{        s = sum[c][ql - 1];        ss = sum[c][qr] - s;    }    if (k <= ss){        return query(c + 1, l, mid, l + s, l + s + ss - 1, k);    }else{        return query(c + 1, mid + 1, r, mid - l + 1 + ql - s, mid - l + 1 + qr - s - ss,k - ss);    }}int main(){    int i, j, k,T;    scanf("%d",&T);    while(T--){    scanf("%d%d", &n, &m);        for (i = 1; i <= n; i++){            scanf("%d", &a[i]);            tree[0][i] = as[i] = a[i];        }        sort(as + 1, as + 1 + n);        build(0, 1, n);        while(m--){            scanf("%d%d%d",&i,&j,&k);query(0, 1, n, i, j, k);            printf("%d\n", ans);        }}    return 0;    } 

0 0