【HDOJ 6231】 k-th number 二分答案
链接
http://acm.hdu.edu.cn/showproblem.php?pid=6231
题意
给你一个数列,对于a中的每个长度大于等于k的区间,把其中第k大的数加进数列b中,求数列b中第m大的数。
solution
二分答案的思想由来
如果任取一个数x作为答案,怎么判断它大了还是小了?如何调整?
- 对于任意一个区间,如果x在其中的排名>m,即比x大的数有至少m个,那么x就不能作为这个区间的结果。
- 如果x满足上述条件,要让x作为区间的结果,需要增大x的值;反之减小x的值。
- 随着x的值增大,在数列b中排名一定会上升。满足单调性。
至此我们可以使用二分答案的做法:
二分答案x的数值大小,即b中排名<=k的( 区间中有至少k个数满足大于等于x 的 区间个数)数的大小。
如果区间个数>=m,表明至少有m个数排在x之前,更新答案,增大x;反之减小x。
code
#include<bits/stdc++.h>
#define ll long long
using namespace std;
const int N = 100005;
const double pi = 3.14159265358979;
ll n,k,m;
int t;
int a[N];
int num[N]={0};
bool check(int mid){
ll cnt=0; //>=mid 的区间的个数
num[0]=0;
for(int i=1;i<=n;i++) num[i]=num[i-1]+(a[i]>=mid);
for(int l=1;l<=n;l++){
int r=lower_bound(num+1,num+n+1,num[l-1]+k)-num;
cnt+=(n-r+1);
}
return cnt>=m;
}
int main(){
cin>>t;
while(t--){
cin>>n>>k>>m;
int l=1e9,r=0,mid,ans;
for(int i=1;i<=n;i++){
scanf("%d",&a[i]);
r=max(a[i],r);
l=min(l,a[i]);
}
while(l<=r){
mid=(l+r)>>1;
if(check(mid)) ans=mid,l=mid+1; // >=mid 的数 >= M 个
else r=mid-1;
}
printf("%d\n",ans);
}
return 0;
}
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· winform 绘制太阳,地球,月球 运作规律
· AI与.NET技术实操系列(五):向量存储与相似性搜索在 .NET 中的实现
· 超详细:普通电脑也行Windows部署deepseek R1训练数据并当服务器共享给他人
· 上周热点回顾(3.3-3.9)
· AI 智能体引爆开源社区「GitHub 热点速览」