P6733 题解
P6733 「Wdsr-2」间歇泉 题解
算法分析
由于 \(k\) 达到了 \(10^{10}\) 的级别,所以正常暴力做法肯定不行,于是考虑二分。
二分 \(mid\)。
注意:实数二分要考虑精度。
check 函数公式推导
当
\[\sum_{i=1}^{n}\sum_{j=1}^{n} [mid \le \frac{a_ic_i+a_jc_j}{a_i+a_j}] \ge k
\]
时返回 true,反之返回 false。
展开,得
\[\sum_{i=1}^{n}\sum_{j=1}^{n} [a_imid+a_jmid \le a_ic_i+a_jc_j] \ge k
\]
移项,得
\[\sum_{i=1}^{n}\sum_{j=1}^{n} [a_ic_i+a_imid \le a_jc_j+a_jmid] \ge k
\]
此时,\(a_ic_i+a_imid\) 与 \(a_jc_j+a_jmid\) 都可以以 \(O(n)\) 的代价预处理出来。
排序后用双指针求出
\(\sum_{i=1}^{n}\sum_{j=1}^{n} [a_imid+a_jmid \le a_ic_i+a_jc_j]\) 的量。
此时,\((i,j)\) 与 \((j,i)\) 都算了一遍。所以,我们再将这个答案除以 \(2\)。
注意:自己与自己不能混和,当 \([a_imid+a_jmid = a_ic_i+a_jc_j]\) 时答案减一。
复杂度
编程语言:C++98 O2;
代码长度:752B;
用时:1.04s;
内存:3.36MB。
理论复杂度 \(O(n \log^2 n)\)。
CODE
#include<bits/stdc++.h>
#define int long long
const int N=1e5+5;
const double eps=1e-4;
int n,k;
double a[N],c[N];
double x[N],y[N];
bool check(double mid){
int res=0;
for(int i=1;i<=n;i++){
x[i]=a[i]*c[i]-a[i]*mid;
y[i]=a[i]*mid-a[i]*c[i];
if(y[i]-x[i]<eps) res--;
}
std::sort(x+1,x+n+1);
std::sort(y+1,y+n+1);
int j=0;
for(int i=1;i<=n;i++){
while(y[j+1]-x[i]<eps&&j<n)j++;
res+=j;
}
return res/2>=k;
}
signed main(){
std::ios::sync_with_stdio(0);
std::cin.tie(0),std::cout.tie(0);
std::cin>>n>>k;
for(int i=1;i<=n;i++)
std::cin>>a[i]>>c[i];
double l=1,r=1e9;
for(int i=1;i<=50;i++){
double mid=(l+r)/2.0;
if(check(mid)) l=mid;
else r=mid;
}
printf("%.3f\n",l);
return 0;
}

浙公网安备 33010602011771号