Search for a command to run...
Progressive hints first, then the full explanation and implementation when you're ready to cash out.
Review status
AI-generated and still unreviewed. Double-check the details before internalizing them.
Hints
Open only as much as you need to keep the solve alive.
Think about the set of points Alice does not remove. Alice’s removed-cost part is just total cost minus the cost of kept points, so the real choice is which nonempty subset to keep.
For a kept subset , the score is
The total cost is fixed, so maximize only the expression in parentheses.
Any kept point that is not responsible for one of only hurts, because costs are nonnegative. So an optimal kept set has at most four meaningful points.
Rewrite width/height with signs:
where each max is taken over the kept points.
This becomes a tiny DP over four “requirements”: pick points to cover the four signed values . If a point is used for several requirements, pay its cost only once. There are only masks, so update DP masks for every point.
Let Alice keep some nonempty set of points . Everything else gets removed.
If , then the final score for this kept set is
So is fixed, and we only need to maximize
Call that value .
The Important Rewrite
The rectangle part can be split into four independent-looking extremes:
All maxes are over points in .
So each kept point can contribute to any subset of these four roles:
A selected point may cover multiple roles. For example, if one point is both the rightmost and topmost kept point, it can provide both and , and we should pay its cost only once.
That “pay once, cover several roles” part is the whole problem. The rest is bookkeeping.
Why This Is Enough
Suppose we already know which points provide the four extreme values. Any other kept point does not change , , , or . Since costs are nonnegative, keeping that extra point only subtracts more cost. So optimal play never needs useless passengers. No freeloaders. Rectangle math is ruthless like that.
Therefore the optimal kept set can be described by assigning each of the four roles to some points. There are only four roles, so we can DP over role masks.
DP Definition
Let
For a mask , define as the best value achievable after covering exactly the set of roles in using some selected points, where selected point costs are already subtracted.
Initially:
and all other states are impossible.
When considering point , we may use it to cover any nonempty subset of the four roles. Its contribution is
Then we transition:
We also keep the option of not using this point.
At the end, all four roles must be covered, so the best kept-set bonus is .
The answer is
One Subtle Point
For , this still works. The only point covers all four roles, contributing
Then , which matches the rule that Alice cannot remove all points.
Complexity
There are masks and nonempty role subsets per point, so the runtime is
which is easily fine for points. Memory is .
#include <bits/stdc++.h>
using namespace std;
using ll = long long;
void setIO() {
ios::sync_with_stdio(false);
cin.tie(nullptr);
}
int main() {
setIO();
int T;
cin >> T;
const ll NEG = -(1LL << 62);
while (T--) {
int n;
cin >> n;
vector<ll> x(n), y(n), c(n);
for (ll &v : x) cin >> v;
for (ll &v : y) cin >> v;
ll total = 0;
for (ll &v : c) {
cin >> v;
total += v;
}
vector<ll> dp(16, NEG);
dp[0] = 0;
for (int i = 0; i < n; i++) {
ll val[4] = {2 * x[i], -2 * x[i], 2 * y[i], -2 * y[i]};
ll add[16] = {};
for (int mask = 1; mask < 16; mask++) {
ll s = 0;
for (int bit = 0; bit < 4; bit++) {
if (mask & (1 << bit)) s += val[bit];
}
add[mask] = s - c[i];
}
vector<ll> ndp = dp;
for (int mask = 0; mask < 16; mask++) {
if (dp[mask] == NEG) continue;
for (int take = 1; take < 16; take++) {
int nmask = mask | take;
ndp[nmask] = max(ndp[nmask], dp[mask] + add[take]);
}
}
dp.swap(ndp);
}
cout << total + dp[15] << '\n';
}
return 0;
}#include <bits/stdc++.h>
using namespace std;
using ll = long long;
void setIO() {
ios::sync_with_stdio(false);
cin.tie(nullptr);
}
int main() {
setIO();
int T;
cin >> T;
const ll NEG = -(1LL << 62);
while (T--) {
int n;
cin >> n;
vector<ll> x(n), y(n), c(n);
for (ll &v : x) cin >> v;
for (ll &v : y) cin >> v;
ll total = 0;
for (ll &v : c) {
cin >> v;
total += v;
}
vector<ll> dp(16, NEG);
dp[0] = 0;
for (int i = 0; i < n; i++) {
ll val[4] = {2 * x[i], -2 * x[i], 2 * y[i], -2 * y[i]};
ll add[16] = {};
for (int mask = 1; mask < 16; mask++) {
ll s = 0;
for (int bit = 0; bit < 4; bit++) {
if (mask & (1 << bit)) s += val[bit];
}
add[mask] = s - c[i];
}
vector<ll> ndp = dp;
for (int mask = 0; mask < 16; mask++) {
if (dp[mask] == NEG) continue;
for (int take = 1; take < 16; take++) {
int nmask = mask | take;
ndp[nmask] = max(ndp[nmask], dp[mask] + add[take]);
}
}
dp.swap(ndp);
}
cout << total + dp[15] << '\n';
}
return 0;
}