POJ 2104 K-th Number(主席树)

来源:互联网 发布:网络脆弱性的原因 编辑:程序博客网 时间:2024/06/06 19:35

K-th Number
Time Limit: 20000MS Memory Limit: 65536KTotal Submissions: 60047 Accepted: 21000Case Time Limit: 2000MS

Description

You are working for Macrohard company in data structures department. After failing your previous task about key insertion you were asked to write a new data structure that would be able to return quickly k-th order statistics in the array segment. 
That is, given an array a[1...n] of different integer numbers, your program must answer a series of questions Q(i, j, k) in the form: "What would be the k-th number in a[i...j] segment, if this segment was sorted?" 
For example, consider the array a = (1, 5, 2, 6, 3, 7, 4). Let the question be Q(2, 5, 3). The segment a[2...5] is (5, 2, 6, 3). If we sort this segment, we get (2, 3, 5, 6), the third number is 5, and therefore the answer to the question is 5.

Input

The first line of the input file contains n --- the size of the array, and m --- the number of questions to answer (1 <= n <= 100 000, 1 <= m <= 5 000). 
The second line contains n different integer numbers not exceeding 109 by their absolute values --- the array for which the answers should be given. 
The following m lines contain question descriptions, each description consists of three numbers: i, j, and k (1 <= i <= j <= n, 1 <= k <= j - i + 1) and represents the question Q(i, j, k).

Output

For each question output the answer to it --- the k-th number in sorted a[i...j] segment.

Sample Input

7 31 5 2 6 3 7 42 5 34 4 11 7 3

Sample Output

563

Hint

This problem has huge input,so please use c-style input(scanf,printf),or you may got time limit exceed.

Source

Northeastern Europe 2004, Northern Subregion

静态求区间第K大,主席树入门经典题目。

主席树(ChairTree树)<=>可持久化线段树,每个节点对应一棵线段树,而相邻的线段树即前缀的公共部分很多,通过共用而达到优化目的。每次要更新每个节点的信息只要新建一个节点代替这个节点,然后把这个节点的孩子指针指向原来节点的孩子,这样在修改一个值的时候,它只要修改logn个节点就可以了。每次更新和查找的时间复杂度和空间复杂度均为O(logn)。


代码:

#include <cstdio>#include <cstring>#include <algorithm>using namespace std;const int N = 100000 + 5;int a[N], b[N], rt[N * 20], ls[N * 20], rs[N * 20], sum[N * 20];int n, m, tot, sz, l, r, k, q, T;void Build(int& o, int l, int r){    o = ++ tot;    sum[o] = 0;    if(l == r) return;    int m = (l + r) >> 1;    Build(ls[o], l, m);    Build(rs[o], m + 1, r);}void update(int& o, int l, int r, int last, int p){    o = ++ tot;    ls[o] = ls[last];    rs[o] = rs[last];    sum[o] = sum[last] + 1;    if(l == r) return;    int m = (l + r) >> 1;    if(p <= m)  update(ls[o], l, m, ls[last], p);    else update(rs[o], m + 1, r, rs[last], p);}int query(int ss, int tt, int l, int r, int k){    if(l == r) return l;    int m = (l + r) >> 1;    int cnt = sum[ls[tt]] - sum[ls[ss]];    if(k <= cnt) return query(ls[ss], ls[tt], l, m, k);    else return query(rs[ss], rs[tt], m + 1, r, k - cnt);}void work(){    scanf("%d%d%d", &l, &r, &k);    int ans = query(rt[l - 1], rt[r], 1, sz, k);    printf("%d\n", b[ans]);}int main(){    while(scanf("%d%d", &n, &m) != EOF){        for(int i = 1; i <= n; i ++)     scanf("%d", a + i), b[i] = a[i];        sort(b + 1, b + n + 1);        sz = unique(b + 1, b + n + 1) - (b + 1);        tot = 0;        Build(rt[0],1, sz);        for(int i = 1; i <= n; i ++)        {     a[i] = lower_bound(b + 1, b + sz + 1, a[i]) - b;update(rt[i], 1, sz, rt[i - 1], a[i]);}         while(m--)    work();    }    return 0;}

原创粉丝点击