K-th Number
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.
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.
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
题意:给你数列A,对于A的每一个区间,求第K大,插入到数列B中,最后再求数列B的第M大!
解题思路:二分答案+尺取法判断。看了题解才会,真的很巧妙,这都能二分。对于当前答案,如果当前答案作为第K大的区间的总数大于M,那么证明实际答案要比当前答案大,反之则小。如果这个能懂的话,就知道怎么二分了。难点变为怎么统计答案作为第K大的区间个数,这里用到了尺取法。尺取法很容易理解,跟着代码跑一边就懂了。
#include<iostream>
#include<deque>
#include<memory.h>
#include<stdio.h>
#include<map>
#include<string.h>
#include<algorithm>
#include<vector>
#include<math.h>
#include<stack>
#include<queue>
#include<set>
using namespace std;
typedef long long int ll;
int N,K;
ll M;
int a[100005];
bool judge(int x){
ll ans=0;//区间个数
int num=0;//当前>x的数的个数
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(judge(m))
l=m+1;
else
r=m;
}
printf("%d\n",l-1);
}
return 0;
}