[poj 2104 K-th Number] 主席树 区间第K大

来源:互联网 发布:阿里云的作用 编辑:程序博客网 时间:2024/05/19 23:53

[poj 2104 K-th Number] 主席树 区间第K大

题目链接:[poj 2104 K-th Number]
题意描述:给定N个数a1,a2,,anM次查询,每次查询区间第L个数到第R个数中的第K大数。
相似题目: [hdu 4417 Super Mario] 主席树+离散化
解题思路:首先对数据离散化。然后线段树记录区间中的数字出现的次数。主席树保存N棵线段树,每棵线段树都保存着前N个数字的信息。查询区间[L,R]的第K大, 只要根据第L1棵数和第R棵树二分向叶子节点就好了。

#include <map>#include <set>#include <queue>#include <cmath>#include <cstdio>#include <string>#include <cstring>#include <iostream>#include <algorithm>using namespace std;//#pragma comment(linker, "/STACK:1024000000,1024000000")#define FIN             freopen("input.txt","r",stdin)#define FOUT            freopen("output.txt","w",stdout)#define fst             first#define snd             second#define __mid__         int mid = ((l + r) >> 1)typedef __int64 LL;typedef unsigned __int64 ULL;typedef pair<int, int> PII;const int MAXN = 100000 + 5;const int MAXM = 5000 + 5;const int INF = 0x3f3f3f3f;int N, M, A[MAXN], F[MAXN], L, R, K;int root[MAXN], FSZ, TSZ;struct TNode {    int ls, rs, sum;} node[MAXN * 20];void hash_init() {    sort(F, F + N);    FSZ = unique(F, F + N) - F;    F[FSZ ++] = INF;}int getID(const int& x) { return lower_bound(F, F + FSZ, x) - F + 1;}int build(int l, int r) {    int rt = TSZ ++;    node[rt].sum = 0;    if(l == r) { node[rt].ls = node[rt].rs = -1; return rt;}    __mid__;    node[rt].ls = build(l, mid);    node[rt].rs = build(mid + 1, r);    return rt;}int update(const int& pos, int r1, int l, int r) {    int r2 = TSZ ++;    node[r2] = node[r1];    node[r2].sum ++;    if(l == r) return r2;    __mid__;    if(pos <= mid) node[r2].ls = update(pos, node[r1].ls, l, mid);    else node[r2].rs = update(pos, node[r1].rs, mid + 1, r);    return r2;}int query(int k, int r1, int r2, int l, int r) {    if(l == r) return l;    __mid__;    int x = node[node[r2].ls].sum - node[node[r1].ls].sum;    if(k <= x) return query(k, node[r1].ls, node[r2].ls, l, mid);    else return query(k - x, node[r1].rs, node[r2].rs, mid + 1, r);}int main() {#ifndef ONLINE_JUDGE    FIN;#endif // ONLINE_JUDGE    while(~scanf("%d %d", &N, &M)) {        for(int i = 0; i < N; i++) scanf("%d", &A[i]), F[i] = A[i];        hash_init();        TSZ = 0;        root[0] = build(1, FSZ);        for(int i = 0; i < N; i++) {            root[i + 1] = update(getID(A[i]), root[i], 1, FSZ);        }        while(M --) {            scanf("%d %d %d", &L, &R, &K);            int ret = query(K, root[L - 1], root[R], 1, FSZ) - 1;            printf("%d\n", F[ret]);        }    }    return 0;}
0 0
原创粉丝点击