题意:
给你一个长度为n的数组, 将所有长度大于k的子串的第k大放入数组B中, 然后询问数组B
的第m大是什么?
题解:
考虑: 二分答案
如果我们知道当前答案为x, 那么怎么判断x是第几大呢, 可以在元素组里面用两个指针 (l, r)
枚举每个位置的(l) 然后走r当出现的大于等于x数字的个数大与 (k)的时候停止 走r, 那么次使就会出现
(n - r + 1)个区间的第k大是大于等于x的, 然后在继续枚举下一个l, 一次类推。
如果当前的答案最后出现大于等于x的区间大小等于m, 那么就二分就想右分, 否则向左分
代码:
#include<bits/stdc++.h>
using namespace std;
const int N = 1e5 + 7;
typedef long long ll;
ll n, m, k, a[N];
bool judge(ll x) {
ll r = 1;
ll cnt = 0;
ll ans = 0;
for (int i = 1; i <= n; i++) {
while (r <= n && cnt < k) {
if (a[r] >= x) cnt++;
r++;
}
if (cnt == k)
ans += (n - r + 2);
if (a[i] >= x) cnt--;
}
if (ans >= m) return true;
return false;
}
int main() {
ios::sync_with_stdio(0);
int t; cin >> t;
while (t--) {
cin >> n >> k >> m;
for (int i = 1; i <= n; i++) {
cin >> a[i];
}
ll l = 1, r = 1e9, ans;
while (l <= r) {
ll mid = (l + r) / 2;
if (judge(mid)) {
ans = mid;
l = mid + 1;
} else {
r = mid - 1;
}
}
cout << ans << endl;
}
}