poj 2104 K-th Number - 经典划分树
Description
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 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
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 - 经典划分树的更多相关文章
- POJ 2104:K-th Number(主席树静态区间k大)
题目大意:对于一个序列,每次询问区间[l,r]的第k大树. 分析: 主席树模板题 program kthtree; type point=record l,r,s:longint; end; var ...
- poj 2104:K-th Number(划分树,经典题)
K-th Number Time Limit: 20000MS Memory Limit: 65536K Total Submissions: 35653 Accepted: 11382 Ca ...
- POJ 2104 K-th Number(划分树)
Description You are working for Macrohard company in data structures department. After failing your ...
- POJ 2104 K-th Number (划分树)
K-th Number Time Limit: 20000MS Memory ...
- hdu 2665 Kth number(划分树)
Kth number Time Limit: 15000/5000 MS (Java/Others) Memory Limit: 32768/32768 K (Java/Others) Total S ...
- poj2104 K-th Number(划分树)
K-th Number Time Limit: 20000MS Memory Limit: 65536K Total Submissions: 66068 Accepted: 23273 Ca ...
- 【POJ 2104】 K-th Number 主席树模板题
达神主席树讲解传送门:http://blog.csdn.net/dad3zz/article/details/50638026 2016-02-23:真的是模板题诶,主席树模板水过.今天新校网不好,没 ...
- K-th Number 【POJ - 2104】【可持久化线段树】
题目链接 因为这道题没有删除修改之类的,所以很多人会用离散化之后的线段树来做,但是实际上(可能是我懒得去做离散化这个操作了),然后就是直接写可持久化线段树,区间的长度就是int的从最小到最大的长度,然 ...
- POJ 2104:K-th Number(整体二分)
http://poj.org/problem?id=2104 题意:给出n个数和m个询问求区间第K小. 思路:以前用主席树做过,这次学整体二分来做.整体二分在yr大佬的指点下,终于大概懂了点了.对于二 ...
随机推荐
- 关于android:screenOrientation="portrait"等
1.android:screenOrientation="portrait",表示当切换横竖屏的时候,屏幕的内容始终以竖屏显示,而不会根据屏幕的方向来显示内容. 2.插入个Andr ...
- JavaWeb学习笔记之JSP(一)
1. JSP: 1.1. 为什么需要 JSP ? 如果使用Servlet程序来输出只有局部内容需要动态改变的网页,但是其中的静态网页内容也需要程序员使用Java语言来进行输出,这就造成了大量代码的冗余 ...
- mysql命中索引规律
就算where条件里写了and两个条件,然后建了2个独立索引,1个组合索引,他具体命中哪个是不确定的,他会根据数据分布情况选择. 比如 possible_keys :f1,f2,f1f2,有三种 ...
- iphone微信长按二维码识别不了
在安卓版的微信长按二维码可以识别(前提是你的微信版本到支持此功能),但是到了苹果版的微信就识别不了,经个人测试发现是缩放的问题: 1.设置了初始缩放设置为1,最大缩放值要>=1,不支持缩放.-- ...
- PHP学习系列(1)——字符串处理函数(4)
16.hebrevc() 函数把希伯来文本从右至左的流转换为左至右的流.它也会把新行 (\n) 转换为 <br />.只有 224 至 251 之间的 ASCII 字符,以及标点符号受到影 ...
- python 的文件操作。
20.文件操作: 1.打开文件: f = open('db','r') 只读 ; f = open('db','w') 只写 ...
- sqlalchemy--group_concat的使用
今天,一个app客户端同事需要我服务器端提供一组数据,这组数据要按类分好,把整个结构都展示给他,他直接使用就可以了.数据大概如下面这种: 同事需要的结构大概就是类型1有多少,分别是什么;类型2有多少, ...
- R: for installing package 'RODBC'
Today, i try to install a package in R named 'DOBDC', while i meet a message: > install.packages( ...
- easyui最小化后停留在页面的右下角
0.此方法没有什么技术含量,纯属于自己瞎想的!如果有的好方法,请留言告之谢谢!! 1.直接上代码: $('#winId').window({ onMinimize: function () { //最 ...
- 使用国内镜像更新sdk方法
使用国内的镜像资源: 1.mirrors.neusoft.edu.cn //东软信息学院 2.ubuntu.buct.edu.cn/ubuntu.buct.cn //北京化工大学 3.mirrors. ...