喵喵喵两次二分喵喵喵

第k大数进阶

一道很妙的两次二分
不要问我怎么想到两次二分的
因为万物皆可二分

第一次二分乘积结果
第二次二分b中符合要求的个数

结果为什么就对了我也不知道
而且我盐重怀疑求得的答案不是a和b数组中的数乘起来的结果

代码

#include<bits/stdc++.h>
using namespace std;
#define in Read()
#define re register
#define NNN 100000
int n,m,k;
int a[NNN],b[NNN];

int in{
	int i=0,f=1;char ch='#';
	while((ch>'9'||ch<'0')&&ch!='-')ch=getchar();
	if(ch=='-'){
		ch=getchar();f=-1;
	}
	while(ch>='0'&&ch<='9')i=(i<<1)+(i<<3)+ch-48,ch=getchar();
	return i*f;
}

int add(int x,int now){
	int l=0,r=m,antimony;
	while(l<=r){
		int mid=(l+r)>>1;
		if(now*b[mid]>x)r=mid-1;
		else l=mid+1,antimony=mid;
	}
	return antimony;
}

int check(int x){
	int sum=0;
	for(re int i=1;i<=n;i++){
		sum+=add(x,a[i]);
	}
	return sum;
}

int main(){
	
	n=in,m=in,k=in;
	for(re int i=1;i<=n;i++)a[i]=in;
	for(re int i=1;i<=m;i++)b[i]=in;
	
	sort(a+1,a+n+1);
	sort(b+1,b+m+1);
	
	int l=a[1]*b[1],r=a[n]*b[m],ans;
	while(l<=r){
		int mid=(l+r+1)>>1;
		if(check(mid)>=k)r=mid-1,ans=mid;
		else l=mid+1;
	}
	printf("%d",ans);
	return 0;
}

还有一个问题
里面l和r怎么跳
一定要小心跳了之后会不会刚好把答案跳掉了
所以令一个Antimony=mid来存储

Oct.30 更
找到原因了
这道题的答案数据就是用标程生成的,因为标程也没有验证答案是否是a和b的乘积
如果真的要得到 a × b a\times b 的话,就用下面的这个微调

 int temp=l;//刚才二分得到的答案
 int tmp=0,ans=a[n]*b[n];
 for(re int i=1;i<=n;i++){
    tmp=Add(a[i],temp);
    if(tmp!=n)
         ans=min(ans,b[tmp]*a[i]);
 }
发布了26 篇原创文章 · 获赞 3 · 访问量 916

猜你喜欢

转载自blog.csdn.net/Antimonysbguy/article/details/102756156
今日推荐