K-th Number
Time Limit: 20000MS   Memory Limit: 65536K
Total Submissions: 47066   Accepted: 15743
Case Time Limit: 2000MS

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
题意:给你有n个元素的数组,q次查询,每次问L,R之间第k大的数是什么。
 
思路:
划分树模板题。
#include<set>
#include<map>
#include<queue>
#include<stack>
#include<cmath>
#include<string>
#include<vector>
#include<cstdio>
#include<cstring>
#include<iostream>
#include<algorithm>
#define INF 1000000001
#define MOD 1000000007
#define ll long long
#define lson l,m,rt<<1
#define rson m+1,r,rt<<1|1
#define pi acos(-1.0)
using namespace std;
const int MAXN = ;
int num[][MAXN],cnt[][MAXN];//num[d][i]表示深度为d第i个数 cnt[d][i]表示深度为d第i个数之前(包括第i个数)小于sor[m]的个数
int n,sor[MAXN];//sor[i]表示快排后的数组
void build(int l,int r,int d)
{
if(l == r){
return ;
}
int m = (l + r) >> ;
int same_m = m - l + ;//same_m表示在[l,r]中和sor[m]相同值得个数 如果有多个sor[m]的值,那么有一部分会放到左孩子。
//这里就是求放到左孩子的值为sor[m]的个数
for(int i = l; i <= r; i++){
if(num[d][i] < sor[m])same_m --;
}
int pl,pr;
int cnt_small = ;//表示当前小于sor[m]的个数
pl = l,pr = m + ;//左右孩子开始的位置
for(int i = l; i <= r; i++){
if(num[d][i] < sor[m]){//如果当前值比sor[m]小 那么会放在左孩子
num[d+][pl++] = num[d][i];
cnt_small ++;
cnt[d][i] = cnt_small;
}
else if(num[d][i] == sor[m] && same_m){//如果当前的值和sor[m]相同,那么就要判断左边的sor[m]是否放满了
same_m --;
cnt_small ++;
cnt[d][i] = cnt_small;
num[d+][pl++] = num[d][i];
}
else {//放右孩子 由于右孩子都比sor[m]大,所以cnt_small不需要加
num[d+][pr++] = num[d][i];
cnt[d][i] = cnt_small;
}
}
build(l,m,d + );
build(m + ,r,d + );
}
void Init()
{
memset(cnt,,sizeof(cnt));
sort(sor+,sor+n+);
build(,n,);
}
int query(int L,int R,int k,int l,int r,int d)//查询区间[L,R]中第K大的值
{
if(l == r){//找到
return num[d][l];
}
int m = (l + r) >> ;
int s, ss;//s表示[l,L)中小于sor[m]的个数 ss表示[L,R]中小于sor[m]的个数
if(l == L)s = ;//如果左边界相同 不能cnt[d][L-1] 因为L-1有可能是别的子树的
else s = cnt[d][L - ];
ss = cnt[d][R] - s;
if(ss >= k){//如果当前区间内左孩子的个数足够k个,那么就要进入左孩子查询
int newl = l + s;//左边会变成l + s 因为左孩子的值都小于sor[m] 建树的时候,数组的相对大小顺序没有改变,也就是说这是一个稳定的排序。
//也就是说从d到d+1时 加入的数 还是按照相对顺序的
//所以这里的新的左边界 就是l + s, 我们要找的d+1层中 左孩子都是小于sor[m]的!!
// s是[l,L)的到左孩子的值, 看) 所以不需要减一
int newr = l + s + ss - ;//同理 不过由于这里 s + ss后就是[l,R] 连起来了 所以需要减一
return query(newl,newr,k,l,m,d + );
}
else {
int a = L - l - s;//不需要加一 因为L这里不算 所以后面的newl需要加1
//a表示[l,L)之间大于sor[m]的个数 也就是要进入右孩子的个数
int b = R - L + - ss;//b表示[L,R]之间 进入右孩子的个数
int newl = m + + a;//右孩子的值都大于sor[m] 所以原来的左边界 在右孩子中会变成 m + 1 + a
int newr = m + a + b;//b是长度 由于m本需要+1 但是由于加了长度就已经+1了 其实是 m + 1 + a + b - 1
return query(newl,newr,k - ss,m + ,r,d + );
}
}
void solve(int q)
{
int x,y,k;
while(q--){
scanf("%d%d%d",&x,&y,&k);
printf("%d\n",query(x,y,k,,n,));
}
}
int main()
{
int q;
int t;
scanf("%d",&t);
while(t--){
scanf("%d%d",&n,&q);
memset(num,,sizeof(num));
for(int i = ; i <= n; i++){
scanf("%d",&num[][i]);
sor[i] = num[][i];
}
Init();
solve(q);
}
return ;
}

hdu2665 && poj2104划分树的更多相关文章

  1. poj2104(划分树模板)

    poj2104 题意 给出一个序列,每次查询一个区间,要求告诉这个区间排序后的第k个数. 分析 划分树模板,O(mlogn). 建树.根据排序之后的数组,对于一个区间,找到中点的数,将整个区间分为左右 ...

  2. poj2104 划分树 区间K大 在线 无修改

    博主sbit....对于高级数据结构深感无力,然后这些东西在OI竟然烂大街了,不搞就整个人都不好了呢. 于是我勇猛的跳进了这个大坑 ——sbit 区间K大的裸题,在线,无修改. 可以用归并树(\(O( ...

  3. 初学划分树,小见解之!POJ-2104/HDU-2665

    划分树 本来是学主席树的,可怜我等巨弱观群巨博客难解fotle主席的思想精髓.于是学了一下划分树,嗯,花了一下午时间理解build(其实自己模拟一遍就通了),我很难理解为什么划分树会看不懂而能学会主席 ...

  4. 划分树(poj2104)

    poj2104 题意:给出n个数,有m次查询,每次查询要你找出 l 到 r 中第 k 大的数: 思路:划分树模板题 上述图片展现了查询时如何往下递推的过程 其中ly表示 [sl,l) 中有多少个数进入 ...

  5. poj2104(划分树模板)

    poj2104 题意 给出一个序列,每次查询一个区间,要求告诉这个区间排序后的第k个数. 分析 划分树模板,O(mlogn). 建树.根据排序之后的数组,对于一个区间,找到中点的数,将整个区间分为左右 ...

  6. poj2104&&poj2761 (主席树&&划分树)主席树静态区间第k大模板

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

  7. poj2104 线段树 划分树

    学习:http://www.cnblogs.com/pony1993/archive/2012/07/17/2594544.html 划分树的build: 划分树是分层构建的,在构建的t层时,我们可以 ...

  8. POJ2104 k-th number 划分树

    又是不带修改的区间第k大,这次用的是一个不同的方法,划分树,划分树感觉上是模拟了快速排序的过程,依照pivot不断地往下划分,然后每一层多存一个toleft[i]数组,就可以知道在这一层里从0到i里有 ...

  9. 划分树 poj2104 hdu5249

    KPI Time Limit: 2000/1000 MS (Java/Others)    Memory Limit: 32768/32768 K (Java/Others) Total Submis ...

随机推荐

  1. POJ1523 SPF[无向图割点]

    SPF Time Limit: 1000MS   Memory Limit: 10000K Total Submissions: 8139   Accepted: 3723 Description C ...

  2. TCP聊天工具

    //前台书写 import java.io.OutputStream; import java.net.InetAddress; import java.net.Socket; import java ...

  3. SQL——查询考试

    一.            设有一数据库,包括四个表:学生表(Student).课程表(Course).成绩表(Score)以及教师信息表(Teacher).四个表的结构分别如表1-1的表(一)~表( ...

  4. Nginx反向代理和负载均衡——个人配置

    #user nobody; worker_processes 2; #error_log logs/error.log; #error_log logs/error.log notice; #erro ...

  5. Canon

    .打开压缩包发现2个文件,1个是加密的zip.zip,另一个是music.mp3.猜测zip.zip的解压密码隐藏在music.mp3里 .用MP3Stego解密music.mp3,密码就是标题的Ca ...

  6. pullRefresh组件配置

    mui.init({ pullRefresh:{ container: '#contanier', indicators:false, up:{ height:200, contentinit: '' ...

  7. JavaScript Math 对象

    JavaScript Math 对象 Math 对象 Math 对象用于执行数学任务. Math 对象并不像 Date 和 String 那样是对象的类,因此没有构造函数 Math(). 语法 var ...

  8. linux安装jdk 不成功,找不到版本问题

    http://www.linuxidc.com/Linux/2015-01/112030.htm 配置文件 export JAVA_HOMEexport JRE_HOMEexport CLASSPAT ...

  9. 内网机(无网络安装 .NET Core win开发环境

    1.安装 vs2015 update3 2.按顺序安装以下包 DotNetCore.1.0.0-SDK.Preview2-x64.exe aspnetcoremodule_x64_en_rc2_14. ...

  10. 详细学习ORACLE JOBS

    一点一点学习jobs的各个方面比较长,比较烦,但是应该看完后会对jobs比较好的应用 一.学习准备 开始dbms_job学习前,先认识一个参数job_queue_processes a.job_que ...