LOJ6796/P8134 Opportunity Cost ICPC World Finals 2020 (拆贡献+状态压缩)

题意即为求 \(\min\limits_{i=1}^n \max\limits_{j=1}^n(\max(x_i-x_j,0),\max(y_i-y_j,0),\max(z_i-z_j,0))\),容易观察到,\(x,y,z\) 任意一项,都会产生对答案有贡献或对答案无贡献两种情况,且我们要求的 \(\max(x_i-x_j,0),\max(y_i-y_j,0),\max(z_i-z_j,0)\) 即为这 \(2^3=8\) 种情况的最大值。我们可以将其状压为一个三位二进制数 \(S\),表示贡献的情况。

然后注意到,对于一个确定的 \(i\),我们要求的是 \(\max\limits_{j=1}^n(\max(0,x_i-x_j,y_i-y_j,z_i-z_j,x_i-x_j+y_i-y_j,\cdots))\),发现 \(x_i,y_i,z_i,x_i+y_i,\cdots\)\(i\) 确定时已经确定可以提出来,剩下的直接对于每种情况 \(S\) 预处理即可。

#define int long long

const int MAXN = 2e5 + 5;
int n, a[MAXN][3], mx[8];

void work() {
	cin >> n;
	for (int i = 1; i <= n; ++i) cin >> a[i][0] >> a[i][1] >> a[i][2];
	for (int S = 0; S < (1ll << 3); ++S) {
		for (int i = 1; i <= n; ++i) {
			int tmp = 0;
			for (int k = 0; k < 3; ++k) {
				if (S >> k & 1) tmp += a[i][k];
			}
			mx[S] = max(mx[S], tmp);
		}
	}
	int ans = LLONG_MAX, ansi = 0;
	for (int i = 1; i <= n; ++i) {
		int anss = 0;
		for (int S = 0; S < (1ll << 3); ++S) {
			int tmp = 0;
			for (int k = 0; k < 3; ++k) {
				if (S >> k & 1) tmp += a[i][k]; 
			}
			anss = max(anss, mx[S] - tmp);
		}
		if (anss < ans) ans = anss, ansi = i;
	}
	cout << ans << ' ' << ansi << endl;
}
posted @ 2024-02-01 16:44  小蛐蛐awa  阅读(50)  评论(0)    收藏  举报