#二分 我们发现答案具有单调性,因为尝试的答案越大满足条件的概率就越高,因此考虑二分。那么,如何判断 $x$ 能不能成为一个正确的答案呢?首先,$a_i-a_{i-1}$ 不能大于 $2x$,因为我们这里只允许添加一个 $d_i+f_j$。然后,不能有两个 $i$ 满足 $a_i-a_{i-1}>x$,原因跟上一个一样。然后就是判断的部分了,如果 $a_i-a_{i-1}$ 不满足条件,那么答案就一定区间 $[a_i-x,a_{i-1}+x]$ 里面,因此我们枚举 $d_i$,然后再二分一个满足条件的 $f_j$ 就行了。注意 $f$ 需要排序。 ```cpp #include <iostream> #include <algorithm> using namespace std; const int kMaxN = 2e5 + 5; int a[kMaxN], d[kMaxN], f[kMaxN], t, n, m, k, ans; bool check(int x) { int cnt = 0, mn, mx, b = 0; for (int i = 2; i <= n; i++) { if (a[i] - a[i - 1] > x) { mn = a[i] - x; mx = a[i - 1] + x; b |= a[i] - a[i - 1] > x * 2; cnt++; } } if (cnt > 1 || b) { return 0; } else if (!cnt) { return 1; } for (int i = 1; i <= m; i++) { int p = lower_bound(f + 1, f + k + 1, mn - d[i]) - f; if (p != k + 1 && d[i] + f[p] >= mn && d[i] + f[p] <= mx) { return 1; } } return 0; } int main() { for (cin >> t; t; t--) { cin >> n >> m >> k; for (int i = 1; i <= n; i++) { cin >> a[i]; } for (int i = 1; i <= m; i++) { cin >> d[i]; } for (int i = 1; i <= k; i++) { cin >> f[i]; } sort(f + 1, f + k + 1); for (int l = 0, r = 2e9; l <= r;) { int mid = (l + r) >> 1; if (check(mid)) { ans = mid, r = mid - 1; } else { l = mid + 1; } } cout << ans << '\n'; } return 0; } ```