hdu-6231 二分

Posted king-of-dark

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了hdu-6231 二分相关的知识,希望对你有一定的参考价值。

  一道二分题目,题目难在不容易看出二分,看出二分难度基本就没了。。。(我不会)

  考虑可以被二分的原因:对于a数组中第k大的数比t大的子串的个数是随着t的减少而严格增大的,所以可以二分t,去寻找答案。

  对于如何查询确定t时,符合条件的子串数量:定义一个右端点和一个左端点,枚举右端点,求每次左端点的最大值,让其包含至少k个大于t的数即可。

  我的思路:我以为是要算每个数被计算的可能性,去求贡献,想了很久都做不出来,感觉二分的方法还是比较独特的,你不能根据每种情况的影响因素去分析如何优化,而是本身题目答案的单调性确保你可以使用二分计算出答案,而和这道题的题目性质本身没有什么关系。如果对二分不是很熟悉的人应该都看不出二分吧。。。因为正常人不会对这种题观察答案的单调性吧。。。

贴一下AC代码

#include <cstdio>
#include <cstring>
#include <algorithm>
#include <cmath>
#include <string>
#include <iostream>
#include <queue>
using namespace std;
const int maxn = 1e5+10;
typedef long long ll;
ll a[maxn],k,n,m;
ll J(int t)

    ll ans=0,num=0;
    for(int i=0,j=-1;i<n;i++)
    
        if(a[i]>=t)
            num++;
        while(i-j>k&&num>=k)
        
            if(a[j+1]<t)
            
                j++;
            
            else
            
                if(num==k)
                
                    break;
                
                else
                
                    num--;
                    j++;
                
            
        
        if(num>=k)
            ans+=j+2;
    
    t;
    return ans;

int main()

    int T;
    cin>>T;
    while(T--)
    
        cin>>n>>k>>m;
        for(int i=0;i<n;i++)
            cin>>a[i];
        int l=0,r=1e9+7,mid=0;
        J(3);
        while(r-1>l)
        
            mid=(l+r)/2;
            if(J(mid)>=m)
            
                l=mid;
            
            else
                r=mid;
        
        if(J(r)>=m)
        
            cout<<r<<endl;
            
        
        else
            cout<<l<<endl;
    

 

以上是关于hdu-6231 二分的主要内容,如果未能解决你的问题,请参考以下文章

HDU 6231(二分&双指针)

hdu 6231 -- K-th Number(二分+尺取)

HDU 6231 (二分+双指针)

HDU - 6231:K-th Number (不错的二分)

HDU - 6231 K-th Number (2017CCPC哈尔滨站 二分+尺取法)

HDU 6231