P6733 「Wdsr-2」间歇泉

题目

P6733 「Wdsr-2」间歇泉_第1张图片

思路

一眼二分
只需要找出有几杯水比当前需要check的温度t大即可
一看到公式,就知道要数学推理了
我们设check的是温度t,第i杯水为被混合的水,第j杯水为要和其他水混合的水,tot为比t温度高的杯数
则只有 a i c i + a j c j a i + a j > = t {a_ic_i+a_jc_j\over a_i+a_j}>=t ai+ajaici+ajcj>=t时才让tot++,除法有误差,换乘法
a i c i + a j c j > = t ( a i + a j ) a_ic_i+a_jc_j>=t(a_i+a_j) aici+ajcj>=t(ai+aj)
a i c i − t a i > = t a j − a j c j a_ic_i-ta_i>=ta_j-a_jc_j aicitai>=tajajcj
a i c i = x a_ic_i=x aici=x t a i = y ta_i=y tai=y,再用两个数组分别存等式两边,
最后用双指针求总杯数
理论存在,时间开始

代码

#include
using namespace std;
#define int long long
const int maxn=1e5+5;
const double eps=1e-9;
int n,k;
int a[maxn],c[maxn];
double p[maxn],q[maxn];
double ans;
struct cmp{ bool operator () (const int &a,const int &b) { return a<b; } };
bool check(double t){
	int tot=0;
	for(int i=1;i<=n;i++){
		double x=a[i]*1.0*c[i],y=t*a[i];
		p[i]=x-y,q[i]=y-x;
		if(q[i]-p[i]<eps) tot--;//不和自己混合
	}
	sort(p+1,p+1+n,cmp()),sort(q+1,q+1+n,cmp());
	int j=0;
	for(int i=1;i<=n;i++){
		while(q[j+1]-p[i]<eps&&j+1<=n) j++;
		tot+=j;
	}
	tot/=2;
	return tot<k;
}
signed main()
{
	cin>>n>>k;
	for(int i=1;i<=n;i++) cin>>a[i]>>c[i];
	double l=1,r=1e9;
	while(r-l>eps){
		double mid=(l+r)/2;
		if(check(mid)) r=mid,ans=mid;
		else l=mid;
	}
	printf("%.3lf",ans);
	return 0;
}

end

完结撒花

你可能感兴趣的:(二分,算法,c++)