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;
}

浙公网安备 33010602011771号