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 -- K-th Number(二分+尺取)
HDU - 6231:K-th Number (不错的二分)