Time Limit: 20000MS | Memory Limit: 65536K | |
Total Submissions: 45147 | Accepted: 15021 | |
Case Time Limit: 2000MS |
Description
Input
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.
题目大意:给出一系列数,求出给定区间的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 + 10 using 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; }