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.

题目意思:给一个数组。问一个区间内第K大的数。

解题思路:划分树。

划分树是基于高速排序的,首先将原始数组a[]进行排序sorted[],然后取中位数m,将未排序数组中小于m放在m左边,大于m的放在m右边,并记下原始数列中每一个数左边有多少数小于m,用数组to_left[depth][]表示,这就是建树过程。

重点在于查询过程。设[L,R]为要查询的区间,[l,r]为当前区间,s 表示[L,R]有多少数放到左子树,ss表示[l,L-1]有多少数被放倒左子树。假设s大于等于K,也就是说第K大的数肯定在左子树里。下一步就查询左子树,但这之前先要更新L,R,新的newl=l+ss,
newr=newl+s-1。假设s小于k,也就是说第k大的数在右子树里,下一步查询右子树,也要先更新L,R,dd表示[l,L-1]中有多少数被放到右子树,d表示[L,R]有多少数被放到右子树,那么newl = m+1+dd,newr=m+d+dd, 这样查询逐渐缩小查询区间,直到最后L==R 返回最后结果即可。

给出一个大牛的图片样例。

watermark/2/text/aHR0cDovL2Jsb2cuY3Nkbi5uZXQv/font/5a6L5L2T/fontsize/400/fill/I0JBQkFCMA==/dissolve/70/gravity/Center" alt="">

代码:

#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 - 经典划分树的更多相关文章

  1. POJ 2104:K-th Number(主席树静态区间k大)

    题目大意:对于一个序列,每次询问区间[l,r]的第k大树. 分析: 主席树模板题 program kthtree; type point=record l,r,s:longint; end; var ...

  2. poj 2104:K-th Number(划分树,经典题)

    K-th Number Time Limit: 20000MS   Memory Limit: 65536K Total Submissions: 35653   Accepted: 11382 Ca ...

  3. POJ 2104 K-th Number(划分树)

    Description You are working for Macrohard company in data structures department. After failing your ...

  4. POJ 2104 K-th Number (划分树)

                                                                K-th Number Time Limit: 20000MS   Memory ...

  5. hdu 2665 Kth number(划分树)

    Kth number Time Limit: 15000/5000 MS (Java/Others) Memory Limit: 32768/32768 K (Java/Others) Total S ...

  6. poj2104 K-th Number(划分树)

    K-th Number Time Limit: 20000MS   Memory Limit: 65536K Total Submissions: 66068   Accepted: 23273 Ca ...

  7. 【POJ 2104】 K-th Number 主席树模板题

    达神主席树讲解传送门:http://blog.csdn.net/dad3zz/article/details/50638026 2016-02-23:真的是模板题诶,主席树模板水过.今天新校网不好,没 ...

  8. K-th Number 【POJ - 2104】【可持久化线段树】

    题目链接 因为这道题没有删除修改之类的,所以很多人会用离散化之后的线段树来做,但是实际上(可能是我懒得去做离散化这个操作了),然后就是直接写可持久化线段树,区间的长度就是int的从最小到最大的长度,然 ...

  9. POJ 2104:K-th Number(整体二分)

    http://poj.org/problem?id=2104 题意:给出n个数和m个询问求区间第K小. 思路:以前用主席树做过,这次学整体二分来做.整体二分在yr大佬的指点下,终于大概懂了点了.对于二 ...

随机推荐

  1. .Net程序员 Solr-5.3之旅 (二)Solr 安装

    阅读目录 引言 Solr5.3环境搭建 Solr5.3创建第一个Core 结尾 引言 一个糟糕的设计有好的表现形式,它会被判死缓,一个好的设计有糟糕的表现形式,它会被判死刑立即执行. 以上摘自一个设计 ...

  2. 关于phonegap

    phonegap安卓环境搭建: http://www.cnblogs.com/Random/archive/2011/12/28/2305398.htmlhttp://ningtukun.blog.1 ...

  3. MVC验证码的编写

    主要是相互学习一下mvc,希望各位大神指导 /// <summary> /// 生成随机数字 /// </summary> /// <returns>随机数字< ...

  4. starting Intent from ProcessRecord with revoked permission android.permission.CALL_PHONE 的错误

    昨天写个电话拨号器,很简单就一个Edittext和一个button,用来输入号码并且点击按钮拨打电话,但是写好以后报的是安全错误,我上网查了下,原来是缺少授权,于是我在AndroidManifest. ...

  5. PHPCMS V9网站更换域名的方法

    网站在发展的过程中,很可能多次的修改域名.那么在phpcms v9中我们要怎么进行设置呢? 请进行以下步骤的修改: 1.修改/caches/configs/system.php里面所有和域名有关的,把 ...

  6. CentOS下php使用127.0.0.1不能连接mysql的解决方法

    这篇文章主要介绍了CentOS下php使用127.0.0.1不能连接mysql的解决方法,本文原因是SELINUX导致的连接失败,需要的朋友可以参考下 php代码很简单: 复制代码代码如下: $ser ...

  7. OpenStack点滴01-概览

    OpenStack项目由Rackspace和NASA(美国国家航空航天局)共同发起,它是一个旨在为公共及私有云的建设与管理提供软件的开源项目. 作为一个开源云平台,OpenStack的首要任务是简化云 ...

  8. Domj4读取xml文件

    节点: Iterator Element.nodeIterator(); //获取当前标签节点下的所有子节点 标签: Element Document.getRootElement(); //获取xm ...

  9. GetMenu返回0解决方法

    在CMainFrame类中找到CMFCMenuBar m_wndMenuBar;这个成员变量,将跟它相关的代码注释掉的话,然后运行,OK.

  10. C/C++堆栈指引(转)

    C/C++堆栈指引 Binhua Liu 前言 我们经常会讨论这样的问题:什么时候数据存储在堆栈(Stack)中,什么时候数据存储在堆(Heap)中.我们知道,局部变量是存储在堆栈中的:debug时, ...