# poj 2104 K-th Number - 经典划分树

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 3
1 5 2 6 3 7 4
2 5 3
4 4 1
1 7 3

Sample Output

5
6
3

Hint

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

#include <cstdio>
#include <algorithm>
#include <iostream>
using namespace std;
#define maxn 100000+100

int val[30][maxn];
int to_left[30][maxn];
int sorted[maxn];
int n;

void build(int l,int r,int d,int rt){
if(l==r) return;
int m = (l+r)>>1;
int lsame = m-l+1;
for(int i=l;i<=r;i++){
if(val[d][i]<sorted[m]) lsame--;
}
int lpos=l,rpos=m+1,same=0;
for(int i=l;i<=r;i++){
if(i==l) to_left[d][i]=0;
else to_left[d][i] = to_left[d][i-1];
if(val[d][i]<sorted[m]){
to_left[d][i]++;
val[d+1][lpos++] = val[d][i];
}else if(val[d][i]>sorted[m]){
val[d+1][rpos++] = val[d][i];
}else{
if(same<lsame){
same++;
to_left[d][i]++;
val[d+1][lpos++] = val[d][i];
}else{
val[d+1][rpos++] = val[d][i];
}
}
}
build(l,m,d+1,rt<<1);
build(m+1,r,d+1,rt<<1|1);
}

void print(){
printf("###\n");
for(int i=0;i<10;i++){
for(int j=1;j<=n;j++){
cout << val[i][j]<<" ";
}
cout << endl;
}
printf("****\n");
for(int i=0;i<10;i++){
for(int j=1;j<=n;j++){
cout << to_left[i][j]<<" ";
}
cout << endl;
}
}

int query(int L,int R,int k,int l,int r,int d,int rt){
if(L==R) return val[d][L];
int s,ss;
if(L==l){
s = to_left[d][R];
ss = 0;
}else{
s = to_left[d][R]-to_left[d][L-1];
ss = to_left[d][L-1];
}
int m = (l+r)>>1;
if(s>=k){
int newl = l+ss;
int newr = newl + s-1;
return query(newl,newr,k,l,m,d+1,rt<<1);
}else{
int bb = (L-1)-l+1-ss;
int b = R-L+1 -s;
int newl = m+1+bb;
int newr = m+bb+b;  // 4 5 1 3 2 (2,5,4)
return query(newl,newr,k-s,m+1,r,d+1,rt<<1|1);
}
}

int main(){
int m;
scanf("%d %d",&n,&m);
for(int i=1;i<=n;i++){
scanf("%d",&val[0][i]);
sorted[i]=val[0][i];
}
sort(sorted+1,sorted+n+1);
build(1,n,0,1);
// print();
while(m--){
int i,j,k;
scanf("%d %d %d",&i,&j,&k);
printf("%d\n",query(i,j,k,1,n,0,1));
}
return 0;
}


• 本文已收录于以下专栏：

## POJ 2104 K-th Number (线段树)

K-th Number Time Limit: 20000MS   Memory Limit: 65536K Total Submissions: 46589   Accepted: 15...

## poj2104K-th Number （主席树）

K-th Number Time Limit: 20000MS   Memory Limit: 65536K Total Submissions: 46886   Accepted: 15...

## 用树解决K-th Number之主席树

K-th Number1.主席树解法前方高能，你需要（一些线段树姿势）答记者问Q：为什么叫主席树？叫主席树会不会给人一种钦定的感觉？ A：因为某大佬考场上忘记怎么写划分树了，于是当场yy出来了，叫主...

## 划分树 K-th Number

K-th Number Time Limit:20000MS     Memory Limit:65536KB     64bit IO Format:%I64d & %I64u Submit S...

## 扩展kmp详解

举报原因： 您举报文章：poj 2104 K-th Number - 经典划分树 色情 政治 抄袭 广告 招聘 骂人 其他 (最多只允许输入30个字)