1. 程式人生 > >HDU 6231 K-th Number——二分+尺取

HDU 6231 K-th Number——二分+尺取

m要開long long,太苟了

首先二分答案,對於二分到的一個數x,我們要判斷大於等於x的數做第k大的區間是否有m個,可以用尺取法,列舉每個左界,對於一個左界求一個右界,使得區間內大於等於x的數有k個,這樣本次列舉就可以為答案貢獻(n-r+1)。

#include <bits/stdc++.h>
using namespace std;
typedef long long ll;
const int maxn = 1e5 + 10;
int T, n, k;
ll m;
int a[maxn], b[maxn];
bool judge(int x) {
    int l = 1, r = 0, cnt = 0;
    ll ans = 0;
    while (r <= n) {
        while (r <= n && cnt != k) if (a[++r] >= x) cnt++;
        while (cnt == k) {
            ans += (n - r + 1);
            if (a[l++] >= x) cnt--;
        }
    }
    return ans >= m;
}
void solve() {
    int l = 1, r = n;
    while (l <= r) {
        int mid = (l + r)>>1;
        if (judge(b[mid])) l = mid + 1;
        else r = mid - 1;
    }
    printf("%d\n", b[r]);
}
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];
        sort(b+1, b+1+n);
        a[n+1] = 0;
        solve();
    }
    return 0;
}