1. 程式人生 > >hdu 2665 Kth number 主席樹

hdu 2665 Kth number 主席樹

Kth number

Time Limit: 15000/5000 MS (Java/Others)    Memory Limit: 32768/32768 K (Java/Others)
Total Submission(s): 12712    Accepted Submission(s): 3871


Problem Description Give you a sequence and ask you the kth big number of a inteval.  
Input The first line is the number of the test cases. 
For each test case, the first line contain two integer n and m (n, m <= 100000), indicates the number of integers in the sequence and the number of the quaere. 
The second line contains n integers, describe the sequence. 
Each of following m lines contains three integers s, t, k. 
[s, t] indicates the interval and k indicates the kth big number in interval [s, t]  
Output For each test case, output m lines. Each line contains the kth big number.  
Sample Input
1 10 1 1 4 2 3 5 6 7 8 9 0 1 3 2  
Sample Output

  
   2
   
  
 

#include <cstdio>
#include <algorithm>
#include <vector>
#include <algorithm>
using namespace std;
const int maxn = 1e5 + 10;
int T, n, m;
int root[maxn * 20], lson[maxn * 20], rson[maxn * 20], sum[maxn * 20];
int a[maxn], cnt;
vector <int> b;

void build(int &o, int l, int r)
{
    o = ++cnt;
    sum[o] = 0;
    if (l == r) return ;
    int m = (l + r) / 2;
    build(lson[o], l, m);
    build(rson[o], m + 1, r);
}

void update(int &o, int l, int r, int last, int pos)
{
    o = ++cnt;
    lson[o] = lson[last];
    rson[o] = rson[last];
    sum[o] = sum[last] + 1;
    if (l == r) return ;
    int m = (l + r) / 2;
    if (pos <= m) update(lson[o], l, m, lson[last], pos);
    else update(rson[o], m + 1, r, rson[last], pos);
}

int query(int start, int end, int l, int r, int k)
{
   if (l == r) return l; 
   int m = (l + r) / 2;
   int cur = sum[lson[end]] - sum[lson[start]];
   if (cur >= k) return query(lson[start], lson[end],l, m, k);
   else return query(rson[start], rson[end], m + 1, r, k - cur); 
}

int main()
{
    scanf("%d", &T);
    while (T--)
    {
        scanf("%d%d", &n, &m);
        b.clear();
        cnt = 0;
        for (int i = 0; i < n; i++)
        {
            scanf("%d", &a[i]);
            b.push_back(a[i]);
        }
        sort(b.begin(), b.end());
        b.erase(unique(b.begin(), b.end()), b.end());
        build(root[0], 1, b.size());
        for (int i = 0; i < n; i++)
        {
            update(root[i + 1], 1, b.size(), root[i], lower_bound(b.begin(), b.end(), a[i]) - b.begin() + 1);
        }
        while (m--)
        {
            int L, R, rank;
            scanf("%d%d%d", &L, &R, &rank);
            printf("%d\n", b[query(root[L - 1], root[R], 1, b.size(), rank) - 1]);
        }
    }
    return 0;
}