K-th Number (POJ_2104) 划分树
来源:互联网 发布:ubuntu 配置ip地址 编辑:程序博客网 时间:2024/06/03 03:12
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 31 5 2 6 3 7 42 5 34 4 11 7 3
Sample Output
563
Hint
This problem has huge input,so please use c-style input(scanf,printf),or you may got time limit exceed.
题目大意:给出一系列数,求出给定区间的Kth值。
解题思路:划分树。
先建树,然后进行查询。
建树的思路为快速排序,小于中位数的放到左边,大于的放到右边。设当前区间为[l,r],当前为第i个数,用left[i]记录[l,i]内有多少个数划入左边区间。
查询思路为不断缩小区间,直到为单位区间(l==r)。难点在于如何在当前的大区间中确定小区间,这时就要用到,前面记录的划入左边区间的个数。首先要比较当前查询区间(ll,rr)划入左区间的个数num=left[ll-1]-left[rr]和k值大小,如果k<=num,则Kth值在左曲建,否则在右区间。
sort[ ][2 3 3 4 4 5 5 7 9]
tree[0][3 5 7 3 4 9 4 2 5]
tree[1][3 3 4 4 2][5 7 9 5]
tree[2][3 3 2][4 4][5 5][7 9]
tree[3][3 2][3][4][4][5][5][7][9]
tree[4][2][3][3][4][4][5][5][7][9]
当在左区间时,小区间为( l+num , l+left[rr]-1 ),查询第k值
当在右区间时,小区间为( mid+1+( ll-l-left[ll-1] ) , mid+1+rr-l-left[ll-1] ),查询第(k-left[ll-1])值
参考博文:http://blog.csdn.net/dyx404514/article/details/8731696
代码如下:
#include"cstdio"#include"iostream"#include"algorithm"#define MAXN 100000 + 10using namespace std;struct seq{int order;int value;}a[MAXN];struct node{//划分树 int val[MAXN];//存值 int left[MAXN];//划入左子树的个数 int deep;//深度 }tree[25];bool cmp(seq a,seq b){return a.value<b.value;} //构建划分树 void Build(int d,int l,int r){if(l==r) return ;int mid=(l+r)>>1;int p=0,t=0;for(int i=l;i<=r;i++){if(tree[d].val[i]<=mid){//划入左子树 tree[d+1].val[l+p]=tree[d].val[i];p++;tree[d].left[i]=p; }else{//划入右子树 tree[d+1].val[mid+1+t]=tree[d].val[i];t++;tree[d].left[i]=p; //是p不是t }}Build(d+1,l,mid);Build(d+1,mid+1,r);}//在大区间(l,r)中查找小区间(ll,rr)的第k大值 int Query(int d,int l,int r,int ll,int rr,int k){ if(ll==rr) return (tree[d].val[ll]);int ls=0,rs=0;//ls,rs用于确定小区间if(ll>l)ls=tree[d].left[ll-1];else ls=0;int mid=(l+r)>>1;rs=tree[d].left[rr];if(rs-ls>=k) return Query(d+1,l,mid,l+ls,l+rs-1,k);else return Query(d+1,mid+1,r,(mid+1)+(ll-l-ls),(mid+1)+rr-l-rs,k-(rs-ls)); if(ll==rr) return tree[d].val[ll];}int main(){int n,m;int i;while(scanf("%d%d",&n,&m)!=EOF){//存值并进行离散化 for(i=1;i<=n;i++){scanf("%d",&a[i].value);a[i].order=i;}sort(a+1,a+1+n,cmp);for(i=1;i<=n;i++){tree[0].val[a[i].order]=i;}Build(0,1,n);while(m--){int ll,rr,k;scanf("%d%d%d",&ll,&rr,&k);printf("%d\n",a[Query(0,1,n,ll,rr,k)].value);}}return 0;}
- K-th Number (POJ_2104) 划分树
- 划分树 K-th Number
- 【划分树】K-th Number
- POJ2104 POJ2761 K-th Number, 划分树
- POJ 2104 K-th Number 划分树
- ★【划分树】K-th Number
- poj 2104 K-th Number--划分树
- poj 2104 K-th Number(划分树)
- POJ 2104 K-th Number 划分树
- 【划分树】K-th Number POJ2104 POJ2761
- [POJ 2104] K-th Number [划分树]
- K-th Number (划分树学习)
- poj 2104 K-th Number(划分树)
- POJ 2104 K-th Number 划分树
- POJ 2104 K-th Number 划分树
- poj2104 K-th Number(划分树)
- poj2104--K-th Number(划分树)
- K-th Number - POJ 2104 划分树
- iOS学习笔记58-iOS- 全方位解析.crash文件崩溃报告
- 任务调度Quartz初探Demo(二)
- Android LayoutInflater详解
- 如何自学Android编程
- 为什么说DOM操作很慢
- K-th Number (POJ_2104) 划分树
- 将一个句子中的单词逆序
- 解决ScrollView嵌套ListView问题的四种方案
- Android的一些设计思想(201603)
- HttpClient的通信
- 27. gnotepad+
- .NET、C#和ASP.NET三才之间的区别
- 2G,3G,4G网络架构浅谈——4G(LTE)
- java调用redis的八种方式