HDU 6231 --- K-th Number(二分+尺取+思维)

K-th Number

Time Limit: 2000/1000 MS (Java/Others)    Memory Limit: 262144/262144 K (Java/Others)
Total Submission(s): 945    Accepted Submission(s): 357


Problem Description
Alice are given an array A[1..N] with N numbers.

Now Alice want to build an array B by a parameter K as following rules:

Initially, the array B is empty. Consider each interval in array A. If the length of this interval is less than K, then ignore this interval. Otherwise, find the K-th largest number in this interval and add this number into array B.

In fact Alice doesn't care each element in the array B. She only wants to know the M-th largest element in the array B. Please help her to find this number.
 

Input
The first line is the number of test cases.

For each test case, the first line contains three positive numbers N(1N105),K(1KN),M. The second line contains N numbers Ai(1Ai109).

It's guaranteed that M is not greater than the length of the array B.
 

Output
For each test case, output a single line containing the M-th largest element in the array B.
 

Sample Input
 
  
2 5 3 2 2 3 1 5 4 3 3 1 5 8 2
 

Sample Output
 
  
3 2
 

Source
 

Recommend
jiangzijing2015   |   We have carefully selected several similar problems for you:   6297  6296  6295  6294  6293
/**
题意:给定一个长度为n的序列a[i],问a序列的所有子序列(连续子区间)的第k大的数组成的数组b的第m大的数;
懵圈了 后来仔细想了一下 是可以二分的;
解题思路:二分x 尺取法找出第k大数大于等于x的连续区间的个数num;
看num和m的关系  若num>m 则说明二分出的x比较小(区间个数过多) 因此需要二分x加大 右移 也就是 l = mid+1; 
若num<m 说明二分出的x比较大 因此需要缩小x 左移 r=mid; 总的来说就是  确定区间的数量和m的关系 来确定二分的走位
求解大于等于k区间的个数 :尺取法
****tricks***
二分角标确定(最大值最小化,最小值最大化均可) 读题 

*/

#include<cstdio>
#include<iostream>
#include<algorithm>
#include<map>
#include<set>
#include<cstring>
#define ll long long
#define inf 0x3f3f3f3f
using namespace std;

const int maxn=1e5+7;
int n,k,a[maxn];
ll m;

bool judge(int x){
	int l=1,num=0;
	ll ans=0;
	for(int i=1;i<=n;i++) {
		if(x<=a[i]) num++;
		if(num==k){
			ans+=n-i+1;
			while(x>a[l]){
				ans+=n-i+1;
				l++;
			}
			num--;
			l++;
		}
	}
	return (ans>=m);
}

void solved(){
	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=1e9+7;
		while(l<r){
			int mid=(l+r)/2;
			if(judge(mid)) l=mid+1;
			else r=mid;
		}
		printf("%d\n",l-1);
	}
}

int main (){
	solved();
	return 0;
}

猜你喜欢

转载自blog.csdn.net/hypHuangYanPing/article/details/80958751