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大佬的指点下,终于大概懂了点了.对于二 ...
随机推荐
- ReSharper warning: Virtual member call in a constructor
1.构造函数的执行顺序是:基类--->派生类 2.如果虚方法被重写后,由于基类中调用了虚方法,此时调用的是最外层的被重写后的虚方法,此时可能会发生异常 举例: class Parent { pu ...
- php单例模式深入讲解
避免多次初始化数据库连接DAO 需要多次初始化数据库连接的场景 场景1: 首先PHP单例模式我觉得只是针对单次页面级请求时出现多个应用场景并需要共享同一对象资源时是非常有意义的 一个类A需要调用多个类 ...
- Android开发手记(14) 使用MediaPlayer播放mp3
1.获取MediaPlayer实例 (1)可以直接通过new或者create方式: 调用setDataSource和create的区别是,create时已经执行了MediaPlayer.prepare ...
- SQL Server 和CLR集成
通过在 Microsoft SQL Server 中托管 CLR(称为 CLR 集成),可以在托管代码中编写存储过程.触发器.用户定义函数.用户定义类型和用户定义聚合函数. 因为托管代码在执行之前会编 ...
- 已经不再更新新浪、网易及CSDN博客了!
RT, 将常驻以下博客: 地址1:51CTO技术博客:http://javalittleman.blog.51cto.com/ 地址2:博客园:http://www.cnblogs.com/javal ...
- iOS中忽略NSLog打印信息(通过PCH文件中定义DEBUG宏解决)
iOS中忽略NSLog打印信息 解决办法: 1.新建PrefixHeader_pch文件,在该文件中定义一下宏 //通过DEBUG宏的定义来解决Debug状态下和Release状态下的输出 #ifde ...
- String类扩展
String s1=new String("fsdfsd"); String s2=new String("fsdfsd"); String a1=" ...
- [转]《深度探索C++对象模型》读书笔记[一]
前 言 Stanley B.Lippman1. 任何对象模型都需要的三种转换风味: ü 与编译器息息相关的转换 ü 语言语义转换 ü 程序代码和对象模型的 ...
- PHP iconv()编码转换函数用法示例
PHP iconv()字符编码转换函数的用法,iconv()函数,在php5中是内置的,语法格式:iconv("UTF- 8","GB2312//IGNORE" ...
- GetMenu返回0解决方法
在CMainFrame类中找到CMFCMenuBar m_wndMenuBar;这个成员变量,将跟它相关的代码注释掉的话,然后运行,OK.