CF685C Optimal Point (数学)

mac2025-05-05  5

题意

三维空间内给n个点,求一个整点使得到所有点的最大曼哈顿距离最小。 n ≤ 1 0 5 n\le10^5 n105

思路

很容易想到二分判定,然后可行域求交。假如是二维的话旋转一下很好做。三维的话旋转不好想象,不如直接用更本质的数学方法。考虑可行域如何表示,二维下只需要四条不等式,三维下需要八条。做一些换元和奇偶讨论即可。具体可参照题解 O ( n log ⁡ x ) O(n\log x) O(nlogx) #include <bits/stdc++.h> #define max(a,b) ((a) > (b) ? (a) : (b)) using namespace std; const int N = 1e5 + 10; typedef long long ll; const ll inf = 4e18; int T, n; ll x[N], y[N], z[N]; ll ansx, ansy, ansz; void upp(ll &x) { ll i = 0; for(i = x / 2 - 3; i * 2 < x; i++); x = i; } void don(ll &x) { ll i = 0; for(i = x / 2 + 3; i * 2 > x; i--); x = i; } bool ok(ll dis) { for(int r = 0; r < 2; r++) { ll amin = -inf, amax = inf; ll bmin = -inf, bmax = inf; ll cmin = -inf, cmax = inf; ll smin = -inf, smax = inf; //2a + r = x+y-z = x0+y0-z0-dis ~ x0+y0-z0+dis //2b + r = x-y+z = x0-y0+z0-dis ~ x0-y0+z0+dis //2c + r = -x+y+z = -x0+y0+z0-dis ~ -x0+y0+z0+dis //2(a + b + c) + 3r = x+y+z = x0+y0+z0-dis ~ x0+y0+z0+dis for(int i = 1; i <= n; i++) { amin = max(amin, ( x[i] + y[i] - z[i] - dis - r)); bmin = max(bmin, ( x[i] - y[i] + z[i] - dis - r)); cmin = max(cmin, (-x[i] + y[i] + z[i] - dis - r)); smin = max(smin, ( x[i] + y[i] + z[i] - dis - 3 * r)); amax = min(amax, ( x[i] + y[i] - z[i] + dis - r)); bmax = min(bmax, ( x[i] - y[i] + z[i] + dis - r)); cmax = min(cmax, (-x[i] + y[i] + z[i] + dis - r)); smax = min(smax, ( x[i] + y[i] + z[i] + dis - 3 * r)); } upp(amin), don(amax); upp(bmin), upp(cmin), upp(smin); don(bmax), don(cmax), don(smax); if (amin > amax || bmin > bmax || cmin > cmax || smin > smax) { continue; } ll sum = amin + bmin + cmin; if (sum > smax) continue; if (sum - amin + amax >= smin) { ll a = amin + max(0, smin - sum); ll b = bmin; ll c = cmin; ansx = a + b + r; ansy = a + c + r; ansz = b + c + r; return 1; } else { sum += amax - amin; if (sum - bmin + bmax >= smin) { ll a = amax; ll b = bmin + max(0, smin - sum); ll c = cmin; ansx = a + b + r; ansy = a + c + r; ansz = b + c + r; return 1; } else { sum += bmax - bmin; if (sum - cmin + cmax >= smin) { ll a = amax; ll b = bmax; ll c = cmin + max(0, smin - sum); ansx = a + b + r; ansy = a + c + r; ansz = b + c + r; return 1; } } } } return 0; } #define abs(x) ((x) > 0 ? (x) : -(x)) void check() { ll mx = 0; for(int i = 1; i <= n; i++) { mx = max(mx, abs(ansx - x[i]) + abs(ansy - y[i]) + abs(ansz - z[i])); } cerr << mx << endl; } int main() { int g = clock(); freopen("c.in", "r", stdin); freopen("c.out","w", stdout); for(cin>>T;T;T--) { scanf("%d", &n); for(int i = 1; i <= n; i++) { scanf("%I64d %I64d %I64d", &x[i], &y[i], &z[i]); } ll l = 0, r = 3e18; int cnt = 0; while (l <= r) { if (ok(l + r >> 1)) { r = (l + r >> 1) - 1; } else { l = (l + r >> 1) + 1; } } check(); printf("%I64d %I64d %I64d\n", ansx, ansy, ansz); } cerr << clock() - g << endl; }
最新回复(0)