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.
Don’t try to model the actual integers written in each round. In one round, the only thing that matters is which circle edges satisfy .
A single round can produce any subset of directed edges except the full set of all edges. All strict inequalities around the whole cycle would say , which is nonsense. Every other subset is feasible.
Let be the number of rounds where edge fired. Then every score must satisfy
So the problem becomes: find edge counts , then find the smallest such that these counts fit into rounds.
For fixed , edge counts are schedulable iff and . The second condition is exactly “each round must leave at least one edge unfired.”
Solve the cyclic equations . If is odd, the solution is unique. If is even, all solutions are one-parameter: choose , then compute the rest by alternation. Minimize over the valid range of .
Reframe The Game
In one round, participant and participant both get a point exactly when the directed edge
“fires”, meaning the chosen numbers satisfy .
So forget the actual numbers for a second. What sets of edges can fire in one round?
The only impossible set is all edges. If all edges fired, we would need
which is a strict cycle, aka mathematical clownery.
Every proper subset is possible. For example, assign numbers while walking around the cycle; as long as at least one edge is not strict, there is no strict contradiction around the whole loop.
So each round is just: choose any subset of edges except the full set.
Edge Counts
Let be the number of rounds in which edge fires.
Participant receives points from exactly two adjacent edges:
Therefore the final scores satisfy
Indices are cyclic, so .
Now the problem is split into two parts:
When Do Edge Counts Fit Into Rounds?
Suppose we already have edge counts .
Clearly each edge can fire at most once per round, so
for every .
Also, every round must leave at least one edge unfired, because the full set of edges is impossible. Across rounds, there are total edge-slots, and edge is used times. So the number of unused slots is
We need at least one unused slot in each round:
which is equivalent to
These conditions are also sufficient. Think of the unused slots as zeros in an binary table. Column needs zeros, and each row needs at least one zero. Since no column needs negative zeros and the total number of zeros is at least , we can place one zero in each row first, then dump the rest wherever capacity remains. Done.
So for fixed , the answer is
Solving
The cyclic equations are linear:
From , everything else is forced:
and so on. Each is either or .
Now parity matters.
Odd
After walking all the way around, the final equation determines uniquely. So there is exactly one solution.
A clean way to compute it:
Set temporarily and generate using
Then the last equation says
For odd , changing by changes by , so the left side changes by . Thus
The statement guarantees the scores are achievable, so this is an integer and all resulting are nonnegative.
Then compute the formula for .
Even
For even , either there are no solutions or infinitely many integer solutions along one parameter. The statement guarantees at least one solution, so we only need optimize.
Again write each edge count as a function of :
Nonnegativity gives an interval of valid values:
For any valid , the answer is
For even , is actually constant, because each score contributes to exactly two edge equations and the alternating degree of freedom just shifts weight between odd and even edges. So the second term is constant.
That leaves minimizing
This is the maximum of some increasing lines and decreasing lines . It is convex over the valid integer interval. The best point is where the biggest increasing requirement and biggest decreasing requirement balance.
Let
and
Then
The real-valued optimum is near
Clamp around that point into and test a few nearby integers. No need for fancy binary search; the function is tiny and convex. The brute force over five candidates is the least dramatic thing here, which is exactly what we want.
Complexity
For each test case we do one or two linear passes over the array.
per test case, and
over the whole input. Memory is if storing the temporary coefficients, or aside from the input. Fast enough; 2400 rating, but no need to summon eldritch data structures.
#include <bits/stdc++.h>
using namespace std;
using ll = long long;
void setIO() {
ios::sync_with_stdio(false);
cin.tie(nullptr);
}
static ll ceil_div(ll a, ll b) {
return (a + b - 1) / b;
}
int main() {
setIO();
int T;
cin >> T;
while (T--) {
int n;
cin >> n;
vector<ll> a(n + 1);
for (int i = 1; i <= n; i++) cin >> a[i];
vector<ll> base(n + 1);
base[n] = 0;
for (int i = 1; i < n; i++) {
base[i] = a[i] - base[i - 1];
}
auto value = [&](const vector<ll>& b) -> ll {
ll mx = 0, sum = 0;
for (int i = 1; i <= n; i++) {
mx = max(mx, b[i]);
sum += b[i];
}
return max(mx, ceil_div(sum, n - 1));
};
if (n & 1) {
ll x = (a[n] - base[n - 1]) / 2;
vector<ll> b(n + 1);
b[n] = x;
for (int i = 1; i < n; i++) b[i] = a[i] - b[i - 1];
cout << value(b) << '\n';
} else {
vector<ll> c(n + 1), sgn(n + 1);
c[n] = 0;
sgn[n] = 1;
for (int i = 1; i < n; i++) {
c[i] = a[i] - c[i - 1];
sgn[i] = -sgn[i - 1];
}
ll L = 0, U = (ll)4e18;
ll P = LLONG_MIN / 4, Q = LLONG_MIN / 4;
ll sum = 0;
for (int i = 1; i <= n; i++) {
if (sgn[i] == 1) {
L = max(L, -c[i]);
P = max(P, c[i]);
} else {
U = min(U, c[i]);
Q = max(Q, c[i]);
}
}
for (int i = 1; i <= n; i++) sum += c[i];
// For even n, sum of b_i(x) is constant because signs cancel.
auto f = [&](ll x) -> ll {
ll mx = 0;
for (int i = 1; i <= n; i++) mx = max(mx, c[i] + sgn[i] * x);
return max(mx, ceil_div(sum, n - 1));
};
ll center = (Q - P) / 2;
ll ans = (ll)4e18;
for (ll dx = -3; dx <= 3; dx++) {
ll x = center + dx;
x = max(L, min(U, x));
ans = min(ans, f(x));
}
ans = min(ans, f(L));
ans = min(ans, f(U));
cout << ans << '\n';
}
}
}#include <bits/stdc++.h>
using namespace std;
using ll = long long;
void setIO() {
ios::sync_with_stdio(false);
cin.tie(nullptr);
}
static ll ceil_div(ll a, ll b) {
return (a + b - 1) / b;
}
int main() {
setIO();
int T;
cin >> T;
while (T--) {
int n;
cin >> n;
vector<ll> a(n + 1);
for (int i = 1; i <= n; i++) cin >> a[i];
vector<ll> base(n + 1);
base[n] = 0;
for (int i = 1; i < n; i++) {
base[i] = a[i] - base[i - 1];
}
auto value = [&](const vector<ll>& b) -> ll {
ll mx = 0, sum = 0;
for (int i = 1; i <= n; i++) {
mx = max(mx, b[i]);
sum += b[i];
}
return max(mx, ceil_div(sum, n - 1));
};
if (n & 1) {
ll x = (a[n] - base[n - 1]) / 2;
vector<ll> b(n + 1);
b[n] = x;
for (int i = 1; i < n; i++) b[i] = a[i] - b[i - 1];
cout << value(b) << '\n';
} else {
vector<ll> c(n + 1), sgn(n + 1);
c[n] = 0;
sgn[n] = 1;
for (int i = 1; i < n; i++) {
c[i] = a[i] - c[i - 1];
sgn[i] = -sgn[i - 1];
}
ll L = 0, U = (ll)4e18;
ll P = LLONG_MIN / 4, Q = LLONG_MIN / 4;
ll sum = 0;
for (int i = 1; i <= n; i++) {
if (sgn[i] == 1) {
L = max(L, -c[i]);
P = max(P, c[i]);
} else {
U = min(U, c[i]);
Q = max(Q, c[i]);
}
}
for (int i = 1; i <= n; i++) sum += c[i];
// For even n, sum of b_i(x) is constant because signs cancel.
auto f = [&](ll x) -> ll {
ll mx = 0;
for (int i = 1; i <= n; i++) mx = max(mx, c[i] + sgn[i] * x);
return max(mx, ceil_div(sum, n - 1));
};
ll center = (Q - P) / 2;
ll ans = (ll)4e18;
for (ll dx = -3; dx <= 3; dx++) {
ll x = center + dx;
x = max(L, min(U, x));
ans = min(ans, f(x));
}
ans = min(ans, f(L));
ans = min(ans, f(U));
cout << ans << '\n';
}
}
}