poj 2104:K-th Number(划分树,经典题)
| Time Limit: 20000MS | Memory Limit: 65536K | |
| Total Submissions: 35653 | Accepted: 11382 | |
| Case Time Limit: 2000MS | ||
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
Source
#include <iostream>
#include <stdio.h>
#include <algorithm>
using namespace std;
#define MAXN 100005
struct Divide_tree{ //划分树的结构(4个数组,2个操作)
int arr[MAXN]; //原数组
int sorted[MAXN]; //排序后数组
int sum[][MAXN]; //记录第i层1~j划分到左子树的元素个数(包括j)
int dat[][MAXN]; //记录第i层元素序列
void build(int c,int L,int R) //建树,主要是建立sum[][]和dat[][]数组
{
int mid = (L+R)>>;
int lsame = mid-L+; //lsame用来记录和中间值val_mid相等的,且可以分到左孩子的数的个数
//简单来说就是可以放入左孩子的,与中间值val_mid相等的数的个数
int lp=L,rp=mid+; //当前节点的左孩子和右孩子存数的起点
for(int i=L;i<mid;i++) //获得一开始的lsame
if(sorted[i]<sorted[mid])
lsame--;
for(int i=L;i<=R;i++){ //从前往后遍历一遍,
//确定当前节点区间内的所有元素的归属(放在左孩子或者放在右孩子)
if(i==L) sum[c][i]=;
else sum[c][i]=sum[c][i-];
if(dat[c][i]<sorted[mid]){ //当前元素比中间值val_mid小,放入左孩子
dat[c+][lp++] = dat[c][i];
sum[c][i]++;
}
else if(dat[c][i]>sorted[mid]) //当前元素比中间值val_mid大,放入右孩子
dat[c+][rp++] = dat[c][i];
else{ //当前元素值与中间值val_mid相等,根据lsame数判断放入左孩子还是右孩子
if(lsame){
lsame--;
sum[c][i]++;
dat[c+][lp++]=sorted[mid];
}
else{
dat[c+][rp++]=sorted[mid];
}
}
}
if(L==R) return ; //递归出口,遇到叶子节点
build(c+,L,mid); //递归进入左孩子区间
build(c+,mid+,R); //递归进入右孩子区间
}
int query(int c,int L,int R,int ql,int qr,int k)
{
//c为树的层数,L,R为当前节点的区间范围,ql,qr为查询的区间范围,k为查询范围内第k大的数
if(L==R) //递归出口,返回第k大的数
return dat[c][L];
int s; //记录[L,ql-1]中进入左孩子的元素的个数
int ss; //记录[ql,qr]中进入左孩子的元素的个数
int mid=(L+R)>>;
if(L==ql){ //端点重合的情况,单独考虑
s=;
ss=sum[c][qr];
}
else {
s=sum[c][ql-];
ss=sum[c][qr]-s;
}
if(k<=ss) //左孩子的元素个数大于k个,说明第k大的元素一定在左孩子区间中,到左孩子中查询
return query(c+,L,mid,L+s,L+s+ss-,k);
else
return query(c+,mid+,R,mid++ql-s-L,mid++qr-s-ss-L,k-ss);
}
};
Divide_tree tree; //定义划分树
int main()
{
int i,L,R,N,M,k;
scanf("%d%d",&N,&M);
for(i=;i<=N;i++){ //输入
scanf("%d",&tree.arr[i]);
tree.sorted[i]=tree.dat[][i]=tree.arr[i];
}
sort(tree.sorted+,tree.sorted+N+);
tree.build(,,N);
for(i=;i<=M;i++){ //M次询问
scanf("%d%d%d",&L,&R,&k);
printf("%d\n",tree.query(,,N,L,R,k));
} return ;
}
poj 2104:K-th Number(划分树,经典题)的更多相关文章
- 【POJ 2104】 K-th Number 主席树模板题
达神主席树讲解传送门:http://blog.csdn.net/dad3zz/article/details/50638026 2016-02-23:真的是模板题诶,主席树模板水过.今天新校网不好,没 ...
- POJ2104 K-th Number 划分树 模板题啊
/*Source Code Problem: 2104 User: 96655 Memory: 14808K Time: 1282MS Language: G++ Result: Accepted S ...
- poj 2104 K-th Number 划分树,主席树讲解
K-th Number Input The first line of the input file contains n --- the size of the array, and m --- t ...
- [hdu2665]Kth number(划分树求区间第k大)
解题关键:划分树模板题. #include<cstdio> #include<cstring> #include<algorithm> #include<cs ...
- 静态区间第k大(划分树)
POJ 2104为例[经典划分树问题] 思想: 利用快速排序思想, 建树时将区间内的值与区间中值相比,小于则放入左子树,大于则放入右子树,如果相等则放入左子树直到放满区间一半. 查询时,在建树过程中利 ...
- HDU-2665-Kth number(划分树)
Problem Description Give you a sequence and ask you the kth big number of a inteval. Input The fir ...
- [NBUT 1458 Teemo]区间第k大问题,划分树
裸的区间第k大问题,划分树搞起. #pragma comment(linker, "/STACK:10240000") #include <map> #include ...
- poj 2104 K-th Number (划分树入门 或者 主席树入门)
题意:给n个数,m次询问,每次询问L到R中第k小的数是哪个 算法1:划分树 #include<cstdio> #include<cstring> #include<alg ...
- POJ 2104 K-th Number(划分树)
题目链接 参考HH大神的模版.对其中一些转移,还没想清楚,大体明白上是怎么回事了,划分树就是类似快排,但有点点区别的.多做几个题,慢慢理解. #include <cstdio> #incl ...
- hdu 2665 Kth number (poj 2104 K-th Number) 划分树
划分树的基本功能是,对一个给定的数组,求区间[l,r]内的第k大(小)数. 划分树的基本思想是分治,每次查询复杂度为O(log(n)),n是数组规模. 具体原理见http://baike.baidu. ...
随机推荐
- QT5笔记:关闭应用程序和窗口的函数
23333 QT一坨,求一门面向傻瓜的语言. QT中 quit(),exit()以及close():常用的三个槽 对主程序的退出,可以调用成员函数exit(),同时也可以调用槽quit(),二者此 ...
- 八数码问题:C++广度搜索实现
毕竟新手上路23333,有谬误还请指正. 课程设计遇到八数码问题(这也是一坨),也查过一些资料并不喜欢用类函数写感觉这样规模小些的问题没有必要,一开始用深度搜索却发现深搜会陷入无底洞,如果设定了深度限 ...
- 3-python学习——变量
变量是我所接触过的编程语言中都具有的一个概念,只是这个概念有的强有的弱罢了. 1.什么是python的变量 变量这个东西怎么解释呢?不怎么好说. 这么说吧,变量就相当于一个代名词,或者说是名字. 计算 ...
- ssh免密码登入
通常做许多事情(git puh/脚本等等),不停输入密码是件很不愉快的事情,破解如下: http://www.linuxproblem.org/art_9.html 1. 生成rsa密钥 ssh-ke ...
- C# 基于json通讯中的中文的处理
如果通讯中产生了\\u4e00-\\u9fa5范围的中文的unicode代码,而不是\u4e00-\u9fa5范围的,那么c#的处理就比较麻烦了. 破解方法: 机制 它会把\\u4e00拆成部分来识别 ...
- Java 日期加减计算.
1.用Java.util.Calender来实现 Calendar calendar=Calendar.getInstance(); calendar.setTime(new Date()) ...
- 网页的title左边的小图片怎么添加
首先,代码中的title标签里是不能加图片的.但是浏览器标提栏前面是可以加一个小图标的. 解决方案:第一步,做一个16 X 16像素的ico格式的图标.具体操作方法是,先在Photoshop中做一个透 ...
- 【GoLang】go 微服务框架 && Web框架学习资料
参考资料: 通过beego快速创建一个Restful风格API项目及API文档自动化: http://www.cnblogs.com/huligong1234/p/4707282.html Go 语 ...
- 【Unity3D】使用鼠标键盘控制Camera视角(即时战略类游戏视角):缩近,拉远,旋转
今天写一个demo,要用到鼠标键盘控制三维视角,因此写了个脚本用于控制. 该脚本可以用于即时战略类游戏的视角,提供了缩进,拉伸,旋转.同时按住鼠标右键不放,移动鼠标可以实现第一人称视角的效果. usi ...
- We7 CMS研究
我下载的we7 3.0是基于vs 2010的,官方网站也建议使用vs2010,但是我有追新的习惯,并相信vs 2013一定能够兼容vs2010的项目,于是在vs2013下打开解决方案并且全部升级,把目 ...