Time Limit: 20000MS | Memory Limit: 65536K | |
Total Submissions: 32718 | Accepted: 10250 | |
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
Source
本题首先给定一序列,要求给定查询区间内序列中的第k小值。
关于区间查询问题,很容易想到线段树。但是本题是要求给定区间的第k小值,线段树并不能很好地解决,线段树适合处理RMQ问题。划分树算法思想参考http://blog.csdn.net/xj2419174554/article/details/10614203
贴个代码,是参考大牛博客http://www.cnblogs.com/kuangbin/category/404860.html的模板
#include<iostream> #include<cstring> #include<cstdio> #include<algorithm> using namespace std; const int MAXN=100000+100; const int MAXPOW=20;//MAXPOW依据MAXN定大小 int tree[MAXPOW][MAXN];//tree[dep][i]表示第dep层第i个位置的值 int sorted[MAXN];//已经排序的数 int toleft[MAXPOW][MAXN];//toleft[dep][i]表示第dep层从1到i进入左边元素的个数 //构建深度为dep、区间为[l,r]的划分树 //时间复杂度为O(N*log(N)) void build(int l,int r,int dep) { int i; if(l==r)return; int mid=(l+r)>>1; int same=mid-l+1;//表示等于中间元素而且被进入左边的元素个数 for(i=l;i<=r;i++) if(tree[dep][i]<sorted[mid]) same--; int lpos=l; int rpos=mid+1; for(i=l;i<=r;i++) { if(tree[dep][i]<sorted[mid])//比中间的元素小,进入左边 tree[dep+1][lpos++]=tree[dep][i]; else if(tree[dep][i]==sorted[mid]&&same>0) { tree[dep+1][lpos++]=tree[dep][i]; same--; } else //比中间的元素大,进入右边 tree[dep+1][rpos++]=tree[dep][i]; toleft[dep][i]=toleft[dep][l-1]+lpos-l;//从1到i放左边的元素个数 } build(l,mid,dep+1); build(mid+1,r,dep+1); } //查询小区间[l,r]内的第k大的元素,[L,R]是覆盖小区间的大区间 //时间复杂度为O(log(N)) int query(int L,int R,int l,int r,int dep,int k) { if(l==r)return tree[dep][l]; int mid=(L+R)>>1; int cnt=toleft[dep][r]-toleft[dep][l-1];//[l,r]中位于左边的元素个数 if(cnt>=k)//进入左子树查询 { //修改小区间的l=L+要查询的区间前进入左边的元素个数 int newl=L+toleft[dep][l-1]-toleft[dep][L-1]; //r=newl+查询区间会被放在左边的元素个数 int newr=newl+cnt-1; return query(L,mid,newl,newr,dep+1,k); } else//进入右子树查询 { //修改小区间的r=r+要查询的区间后进入左边的元素个数 int newr=r+toleft[dep][R]-toleft[dep][r]; //l=r-要查询的区间进入右边的元素个数 int newl=newr-(r-l-cnt); return query(mid+1,R,newl,newr,dep+1,k-cnt); } } int main() { int n,m,i; int l,r,k; while(~scanf("%d%d",&n,&m)) { memset(tree,0,sizeof(tree));//这个必须 for(i=1;i<=n;i++)//从1开始 { scanf("%d",&tree[0][i]); sorted[i]=tree[0][i]; } sort(sorted+1,sorted+n+1); build(1,n,0); while(m--) { scanf("%d%d%d",&l,&r,&k); printf("%d\n",query(1,n,l,r,0,k)); } } return 0; }