题解:P6733 「Wdsr-2」间歇泉
注意到 \(1 \le k \le 10^{10}\),所以暴力求解别想了。
那么另外一种求第 \(k\) 大的方式就是二分答案。
二分答案本身应该不用说了,重要的在于判断的函数。
题目里面并没有给出温度的计算方式,那么根据物理学的角度,两杯水混合后温度为 \(\frac{a_i \times c_i + a_j \times c_j}{a_i + a_j}\)。
所以对于一个数对 \((i, j)\),需要满足 \(\frac{a_i \times c_i + a_j \times c_j}{a_i + a_j} \ge v\),我们称它是合法的。
为了方便计算和预处理我们进行变形。
显然 \(a_i + a_j > 0\),所以根据初中不等式的变形可以得到一个合法的 \((i, j)\),\(a_i \times c_i + a_j \times c_j \ge v \times (a_i + a_j)\)。
把含 \(i\) 的值放在左边,含 \(j\) 的放在右边,得到 \(a_i \times c_i - a_i \times v \ge a_j \times c_j - a_j \times v\)。
将他们分别求出并存储在数组中。
代码:
for(int i = 1; i <= n; i++){
double x = 1.0 * a[i] * c[i], y = mid * a[i];
a[i] = x - y, b[i] = y - x;
if(b[i] - a[i] < eps) tot--;
}
然后问题就转变成了:
对于两个数组 \(a, b\),求出有多少对 \((i, j)\),满足 \(a_i \ge b_j\)。
对于上面的问题可以将两个数组排序,并使用双指针完成。
代码:
sort(a + 1, a + n + 1);
sort(b + 1, b + n + 1);
int j = 0;
for(int i = 1;i <= n; i++){
while((b[j + 1] - a[i]) < eps && j + 1 <= n)
j++;
tot += j;
}
return tot / 2 < k;
需要注意的是,题目中给出了精度误差,所以在判断的时候需要加入 \(eps\) 来防止出错。

浙公网安备 33010602011771号