题目链接:http://acm.hdu.edu.cn/showproblem.php?pid=6231
题意:给出一个数组a 将其所有子段中的第k大的数字放进b中,求b中的第m大的数字。
思路:二分答案,尺取check,尺取的目的是判断大于等于x为第k大的区间有多少个。枚举每一个左端点l,使得整个区间内的大于等于x的数为k个,此时符合条件的区间数要加上(n-r)
因为当右端点在[r,n-1]这个区间内时,去k大值一定是大于等于x的。
#include<cstdio> #include<cstring> #include<algorithm> #include<cmath> #include<map> #include<queue> #define ll long long #define inf 0x3f3f3f3f using namespace std; int N,K; ll M; int a[100005]; bool check(int x) { ll ans=0; int num=0; int j=1; for(int i=1;i<=N;i++) { if(a[i]>=x) num++; if(num==K) { ans+=N-i+1;//统计后面一共可以形成多少个区间 while(a[j]<x) { ans+=N-i+1;//统计前面一共可以形成多少个区间 j++; } num--;//还原状态 j++; } } if(ans>=M) return true; else return false; } int main() { int t; scanf("%d",&t); while(t--) { scanf("%d%d%lld",&N,&K,&M); for(int i=1;i<=N;i++) scanf("%d",&a[i]); int l=1,r=1000000000; int m; while(l<r) { m=(l+r)/2; if(check(m)) l=m+1; else r=m; } printf("%d ",l-1); } return 0; }