← 全部文章

CF685C Optimal Point 题解

本文目录(3 节)
  1. 题意
  2. 题解
  3. 代码

CF685C Optimal Point

题意

  • 立体直角坐标系中有 nn 个整点。
  • 求一个整点满足到这 nn 个整点的曼哈顿距离的最大值最小。
  • n≤105n \le 10^5。

题解

显然先二分答案。

考虑如何 check,假设此时二分到的值为 dd。

则我们可以得到 nn 个限制 ∣x−xi∣+∣y−yi∣+∣z−zi∣≤d|x - x_i| + |y - y_i| + |z - z_i| \le d。

不妨设 xi=yi=zi=0x_i = y_i = z_i = 0,我们考虑 ∣x∣+∣y∣+∣z∣≤d|x| + |y| + |z| \le d 的情况。

枚举每个绝对值取正取负,我们可以列出 23=82^3 = 8 个不等式。

合并这 8n8n 个不等式,最终会得到一个不等式组:

{l≤x+y+z≤rlx≤−x+y+z≤rxly≤x−y+z≤rylz≤x+y−z≤rz \begin{cases}l \leq x+y+z \leq r \\\\lx \leq-x+y+z \leq rx \\\\ly \leq x-y+z \leq ry \\\\lz \leq x+y-z \leq rz\end{cases}

设 a=−x+y+za=-x+y+z,b=x−y+zb=x-y+z,c=x+y−zc=x+y-z,则 x=b+c2x=\frac{b+c}{2},y=a+c2y=\frac{a+c}{2},z=a+b2z=\frac{a+b}{2},且 x+y+z=a+b+cx+y+z = a+b+c,且 a,b,ca,b,c 奇偶性相同。

令 a=2a′+ra = 2a^{\prime} + r,b=2b′+rb = 2b^{\prime} + r,c=2c′+rc = 2c^{\prime} + r,其中 r∈[0,1]r \in [0,1],则我们最终得到的不等式组为: {l′≤a′+b′+c′≤r′lx′≤a′≤rx′ly′≤b′≤ry′lz′≤c′≤rz′ \begin{cases}l^{\prime} \leq a^{\prime}+b^{\prime}+c^{\prime} \leq r^{\prime} \\\\lx^{\prime} \leq a^{\prime} \leq rx^{\prime} \\\\ly^{\prime} \leq b^{\prime} \leq ry^{\prime} \\\\lz^{\prime} \leq c^{\prime} \leq rz^{\prime}\end{cases} 我们要求出这个不等式组的一组解。

先贪心的设 a′=lx′a^{\prime} = lx^{\prime},b′=ly′b^{\prime} = ly^{\prime},c′=lz′c^{\prime} = lz^{\prime},若不满足 l′≤a′+b′+c′≤r′l^{\prime} \leq a^{\prime}+b^{\prime}+c^{\prime} \leq r^{\prime},则一个一个调大 a′,b′,c′a^{\prime}, b^{\prime}, c^{\prime}。

这样我们就可以 O(n)\mathcal O(n) check 并构造了,时间复杂度 O(nlog⁡w)\mathcal O(n \log w)。

说句题外话,代码不太会写,偷偷看一眼兔兔的,发现他偷偷看了题解代码(

代码

const int N = 1e5 + 7;
const ll inf = 4e18;
#define Max(a, b) (a = a > b ? a : b)
#define Min(a, b) (a = a < b ? a : b)
int n;
ll x[N], y[N], z[N], X, Y, Z, mx, mxx, mxy, mxz, mn, mnx, mny, mnz;

inline bool pd(ll o) {
	mx = mxx = mxy = mxz = inf, mn = mnx = mny = mnz = -inf;
	for (int i = 1; i <= n; i++)
		Min(mx, o + x[i] + y[i] + z[i]),
		Min(mxx, o - x[i] + y[i] + z[i]),
		Min(mxy, o + x[i] - y[i] + z[i]),
		Min(mxz, o + x[i] + y[i] - z[i]),
		Max(mn, -o + x[i] + y[i] + z[i]),
		Max(mnx, -o - x[i] + y[i] + z[i]),
		Max(mny, -o + x[i] - y[i] + z[i]),
		Max(mnz, -o + x[i] + y[i] - z[i]);
	for (int i = 0; i < 2; i++) {
		ll l = mn + ((mn & 1) ^ i), r = mx - ((mx & 1) ^ i);
		ll lx = mnx + ((mnx & 1) ^ i), rx = mxx - ((mxx & 1) ^ i);
		ll ly = mny + ((mny & 1) ^ i), ry = mxy - ((mxy & 1) ^ i);
		ll lz = mnz + ((mnz & 1) ^ i), rz = mxz - ((mxz & 1) ^ i);
		if (l > r || lx > rx || ly > ry || lz > rz) continue;
		ll a = lx, b = ly, c = lz;
		if (a + b + c > r) continue;
		if (a + b + c < l) a = rx < l - b - c ? rx : l - b - c;
		if (a + b + c < l) b = ry < l - a - c ? ry : l - a - c;
		if (a + b + c < l) c = rz < l - a - b ? rz : l - a - b;
		if (a + b + c < l) continue;
		return X = (b + c) >> 1, Y = (a + c) >> 1, Z = (a + b) >> 1, 1;
	}
	return 0;
}

inline void solve() {
	rd(n);
	for (int i = 1; i <= n; i++) rd(x[i]), rd(y[i]), rd(z[i]);
	ll l = 0, r = inf;
	while (l <= r) {
		ll mid = (l + r) >> 1;
		if (pd(mid)) r = mid - 1;
		else l = mid + 1;
	}
	print(X, ' '), print(Y, ' '), print(Z);
}

int main() {
	int T;
	rd(T);
	while (T--) solve();
	return 0;
}

标签:二分、构造、贪心

评论

    填写昵称即可留言。评论经站主审核后公开,请勿提交私人信息。

    正在连接评论服务…