ABC279F 并查集题解

  • ~1.71K 字
  1. 1. 题意
  2. 2. 分析
  3. 3. 代码

“我仍然在无人问津的阴雨霉湿之地” —— 《世末歌者》

题意

高橋君有 NN 瓶糖水,青木君有 MM 瓶糖水。

高橋君的第 ii 瓶糖水有 AiA_i 份糖 BiB_i 份水。

青木君的第 ii 瓶糖水有 CiC_i 份糖 DiD_i 份水。

将两人的糖水各选一瓶混合有 NMNM 种可能,求其中浓度第 kk 大的糖水浓度是多少。

xx 份糖和 yy 份水的糖水浓度是 100xx+y%\dfrac{100x}{x+y}\%

分析

二分浓度 cc 后,我们只需要得到混合后浓度大于等于 cc 的个数。

aa 份糖 bb 份水的糖水,再加 (a+b)ca(a+b)c-a 份糖就能变成浓度 cc,也可能是减掉糖。

(a+b)ca(a+b)c-assss 的正负可以判断浓度和 cc 的关系。

那么两瓶糖水 x,yx,y 混合后,判断 sx+sys_x+s_y 的正负即可。

因为 (Ax+Bx+Cy+Dy)cAxCy=(Ax+Bx)cAx+(Cy+Dy)cCy=sx+sy(A_x+B_x+C_y+D_y)c-A_x-C_y=(A_x+B_x)c-A_x+(C_y+D_y)c-C_y=s_x+s_y,所以 ss 是可加的。

二分浓度,将青木君糖水的 ss 排序,枚举高橋君的糖水,二分计算混合后浓度大于等于 cc 的个数。

复杂度 O(nlognlogv)O(n \log n \log v)

代码

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
const int N = 50005;
const double eps = 1e-12;
vector<pair<int,int>> a,b;
int n,m,K;

inline int check(double c){
vector<double> w1,w2;
for(auto [x,y]:a)
w1.push_back(x-(x+y)*c);
for(auto [x,y]:b)
w2.push_back(x-(x+y)*c);
sort(w2.begin(),w2.end());
int ans = 0;
for(auto c:w1)
ans += lower_bound(w2.begin(),w2.end(),-c+eps)-w2.begin();
return ans;
}

signed main(){
cin >> n >> m >> K;
a.resize(n);
b.resize(m);
for(auto &[x,y]:a)
cin >> x >> y;
for(auto &[x,y]:b)
cin >> x >> y;
double l = 0,r = 1;
K = n*m-K+1;
while(abs(r-l)>eps){
double mid = (l+r)/2;
if(check(mid)>=K)
r = mid;
else
l = mid;
}
printf("%.10lf",r*100);
return 0;
}