您的位置:首页 > 其它

K-th Number HDU - 6231 (二分+尺取)(好题)

2017-11-15 21:16 459 查看
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(1≤N≤105),K(1≤K≤N),M.
The second line contains
N
numbers
Ai(1≤Ai≤109).

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

题意:懒得说了思路:这题最大的难点就是想到二分了,为什么可以想到二分呢,因为对于把数组里的数,我们显然可以通过二分确定位置,但是如果把b数组直接表示出来,显然是不能的,但是分析发现,如果我们通过二分去确定位置,我们只用知道比当前数大的数有多少个,那么我们在分析可以知道,只要当某个区间的第k大的数大于等于当前二分的数,剩下包含这个区间的区间都不用考虑了,如果小于的话只用吧终点往后移动,所以每一个数最多遍历两次,当然就是尺取了,那么怎么知道当前区间的第k大呢,一开始我都想用主席树了,但是其实不用我们只用维护当前区间大于等于x的个数就行了ac代码:
#include<bits/stdc++.h>
#define LL long long
#define INF 0x3f3f3f3f
#define INFLL 0x3f3f3f3f3f3f3f
#define lson rt<<1
#define rson rt<<1|1
using namespace std;
const int maxn = 1e5+50;
int n,k;
int a[maxn];
LL m;
int T;
int b[maxn];
int check(int x)
{
int l = 1;
int r = 1;
LL sum1 = 0;//xiaoyudengyu
LL sum2 = 0;//dayu
int nowk;
int cnt = 0;
if(a[l]>=x){
cnt++;
}
while(l<=r&&r<=n){
if(r-l+1>=k){
// cout<<"nowk: "<<nowk<<' '<<l<<' '<<r<<endl;
if(cnt>=k){
sum1+=(n-r+1);
if(a[l]>=x){
cnt--;
}
l++;
}
else{
r++;
if(r>n){
break;
}
if(a[r]>=x){
cnt++;
}
}
}
if(r-l+1<k){
r++;
if(a[r]>=x){
cnt++;
}
}
}
//cout<<x<<' '<<sum1<<endl;
if(sum1>=m){
return 1;
}
else{
return 0;
}
}
int main()
{
scanf("%d",&T);
while(T--){
scanf("%d%d%lld",&n,&k,&m);
for(int i = 1;i<=n;i++){
scanf("%d",&a[i]);
b[i] = a[i];
}
// build(1,1,n);
sort(b+1,b+n+1);
int l = 0;
int r = n+1;
int mid;
while(r>l+1){
mid = (l+r)/2;
if(check(b[mid])){
l = mid;
}
else{
r = mid;
}
}

// cout<<r<<endl;
printf("%d\n",b[l]);
}
}
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签:  ACM 二分