K-th Number
Time Limit: 2000/1000 MS (Java/Others) Memory Limit: 262144/262144 K (Java/Others)Total Submission(s): 635 Accepted Submission(s): 247
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
Source
最近感觉遇到瓶颈了
可能还是太贪玩了吧=0=
给你三个数字 n, k, m (我的变量命名为 n m w= =)
题意看起来挺乱
将所有长度大于 k 的区间的第 k 大的数提取出来
丢到一个新的数组里B
然后输出这个数组B的第 m 大
因为 n 为 1e5
所以数组 B 中最多会有 1e10个元素
所以肯定不可能直接模拟
那么我们考虑二分答案
对于二分出来的 mid
我们统计出区间的第 k 大 大于 mid 的区间个数 num
如果 num 大于 m
那就说明 mid 太小了
反之则说明 mid 太大了
接着就剩下怎么 O(n)的找出 num
考虑尺取
cnt 表示 [l, r]区间内大于等于 mid 的数字个数
当 cnt < k
移动 r
当cnt == k的时候
说明
[l, r] ~ [l, n - 1] (因为我的下标从 0 开始)的区间第 k 大都是大于 mid 的
所以 num += n - r
然后移动 l
重新回想起来了二分的精髓 —— 根本不需要在意是如何算出来的 只需要无限的缩小答案的选择区间就好了
#include <bits/stdc++.h>
#define LL long long
using namespace std;
const int N = 100010;
LL n, m, w;
int ma[N];
int mb[N];
bool check(int x)
{
int l;
int r;
int cnt;
LL sum;
cnt = 0;
sum = 0;
l = 0;
r = -1;
while(r < n){
if(cnt < m){
r ++;
if(ma[r] >= x){
cnt ++;
}
}
else{
sum += (n - r);
if(ma[l] >= x){
cnt --;
}
l ++;
}
}
if(sum >= w){
return true;
}
else{
return false;
}
}
int main()
{
int ncase;
int l, r;
int ans;
scanf("%d", &ncase);
while(ncase --){
scanf("%d%d%d", &n, &m, &w);
for(int i = 0; i < n; i ++){
scanf("%d", &ma[i]);
mb[i] = ma[i];
}
sort(mb, mb + n);
l = 0;
r = n - 1;
while(l <= r){
int mid = l + ((r - l) >> 1);
int t;
t = mb[mid];
if(check(t)){
ans = t;
l = mid + 1;
}
else{
r = mid - 1;
}
}
printf("%d\n", ans);
}
return 0;
}