zoukankan      html  css  js  c++  java
  • HDU 6231 K-th Number 二分+尺取

    题意: 给你一个序列A,对于所有长度大于等于K的子区间,取出每个区间的第K大的数,组成的B序列,输出B序列第M大的数
    ·
    ·
    ·
    二分答案,check(x)函数是用尺取法计算B序列中大于等于x的数的数量
    有一点需要注意的是,二分时if和else里面的内容不能调换,因为check(x)返回的是B序列中大于等于x的数的数量,当check(x) == m时,x可能就是答案,也可能是比答案略小的数,所以要l == mid + 1

    个人以为这方法挺巧的,所以记录一下,详见代码

    #include <bits/stdc++.h>
    using namespace std;
    typedef long long ll;
    const int maxn = 1e5 + 5;
    ll n, k, m, a[maxn];
    ll check(ll x)
    {
        ll ans = 0;
        int cnt = 0, pos = 0;
        for (int i = 1; i <= n; i++)
        {
            while (cnt < k && pos < n)
            {
                if (a[++pos] >= x)
                    cnt++;
            }
            if (cnt == k)
                ans += n - pos + 1;
            if (a[i] >= x)
                cnt--;
        }
        return ans;
    }
    int main()
    {
        int T;
        scanf("%d", &T);
        while (T--)
        {
            scanf("%lld%lld%lld", &n, &k, &m);
            for (int i = 1; i <= n; i++)
                scanf("%lld", &a[i]);
            ll l = 1, r = 1e9, ans = 0;
            while (l <= r)
            {
                ll mid = (l + r) >> 1;
                if (check(mid) >= m)
                {
                    ans = mid;
                    l = mid + 1;
                }
                else
                    r = mid - 1;
            }
            printf("%lld
    ", ans);
        }
        return 0;
    }
    
  • 相关阅读:
    抓老鼠
    我的寒假作业
    寒假作业
    大一上学期C语言学习总结
    我的三位老师
    自我介绍
    2019春季第七周作业
    第六周总结
    第五周作业及其总结
    2019春季第四周作业
  • 原文地址:https://www.cnblogs.com/Zeronera/p/11715617.html
Copyright © 2011-2022 走看看