区间第k大的数 划分树模板

来源:互联网 发布:淘宝积分兑换购物券 编辑:程序博客网 时间:2024/05/22 02:27

一个长度为N的整数序列,编号0 - N - 1。进行Q次查询,查询编号i至j的所有数中,第K大的数是多少。
例如: 1 7 6 3 1。i = 1, j = 3,k = 2,对应的数为7 6 3,第2大的数为6。
Input
第1行:1个数N,表示序列的长度。(2 <= N <= 50000)
第2 - N + 1行:每行1个数,对应序列中的元素。(0 <= Sii <= 10^9)
第N + 2行:1个数Q,表示查询的数量。(2 <= Q <= 50000)
第N + 3 - N + Q + 2行:每行3个数,对应查询的起始编号i和结束编号j,以及k。(0 <= i <= j <= N - 1,1 <= k <= j - i + 1)
Output
共Q行,对应每一个查询区间中第K大的数。
Sample Input
5
1
7
6
3
1
3
0 1 1
1 3 2
3 4 2
Sample Output
7
6
1

参考:http://blog.csdn.net/shiqi_614/article/details/8041390

代码:

#include<bits/stdc++.h>const int INF  = 0x3f3f3f3f;const int Maxn = 100005;#define MST(s,q) memset(s,q,sizeof(s))#define Lchild id<<1#define Rchild (id<<1)+1using namespace std;int order[Maxn], tree[20][Maxn], toleft[20][Maxn];void build(int L, int R, int id) {    if (L == R) return;    int mid = (L + R) >> 1;    int same = mid - L + 1, Ln = L, Rn = mid + 1;    for (int i = L; i <= R; i++)        if (tree[id][i] < order[mid])            same--;    for (int i = L; i <= R; i++) {        int flag = 0;        if (tree[id][i] < order[mid] || (tree[id][i] == order[mid] && same > 0)) {            flag = 1;            tree[id + 1][Ln++] = tree[id][i];            if (tree[id][i] == order[mid])same--;        } else {            tree[id + 1][Rn++] = tree[id][i];        }        toleft[id][i] = toleft[id][i - 1] + flag;    }    build(L, mid, id + 1);    build(mid + 1, R, id + 1);}int query(int s, int e, int k, int L, int R, int id) {    if (L == R) return tree[id][L];    int mid = (L + R) >> 1;    int Lx = toleft[id][s - 1] - toleft[id][L - 1];    int Ly = toleft[id][e] - toleft[id][s - 1];    int Rx = s - 1 - L + 1 - Lx;    int Ry = e - s + 1 - Ly;    if (Ry >= k) return query(mid + 1 + Rx, mid + 1 + Rx + Ry - 1, k, mid + 1, R, id + 1);    else return query(L + Lx, L + Lx + Ly - 1, k - Ry, L, mid, id + 1);////    if (Ly >= k) return query(L + Lx, L + Lx + Ly - 1, k, L, mid, id + 1);//    else return query(mid + 1 + Rx, mid + 1 + Rx + Ry - 1, k - Ly, mid + 1, R, id + 1);}int main() {    int N, M;    while (cin >> N) {        MST(tree, 0);        MST(toleft, 0);        for (int i = 1; i <= N; i++)            scanf("%d", &tree[0][i]);        for (int i = 1; i <= N; i++) order[i] = tree[0][i];        sort(order + 1, order + 1 + N);        build(1, N, 0);        cin >> M;        int a, b, k;        while (M--) {            scanf("%d%d%d", &a, &b, &k);            cout << query(a + 1, b + 1, k, 1, N, 0) << endl;        }    }}
0 0
原创粉丝点击