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.
Project every disk onto the -axis. Disk becomes the interval . Tangency means the right endpoint of one interval equals the left endpoint of the next one.
Non-adjacent disks can never be tangent. If disk has positive radius, then between disk and disk there is a strict bit of interval, so equality is impossible. So only adjacent pairs matter.
Let . The problem is now: choose with , and maximize how many of these inequalities are equalities.
After processing a prefix, look at possible values of the current radius if we have at least tangencies. These possible values form open intervals. If the current interval is and the next gap is , making the next pair tangent maps it to .
The key greedy invariant: every non-best count can realize the whole interval . Only the best count has a special interval . If , extend the best answer. Otherwise, the best state cannot even fit through this gap, so rebuild the same answer from the second-best state.
Let disk project onto the -axis as
Because all centers are on one line, two disks overlap exactly when these intervals overlap with positive length. Tangency between means
Only Adjacent Pairs Matter
Here is the first trap: you might think far-apart disks can also be tangent. Nope.
Let and . Since the centers are sorted and disks do not overlap, adjacent intervals satisfy
Also every radius is positive, so
For , we get a chain like
so actually . Therefore disk and disk cannot be tangent. The middle positive-radius disk blocks exact contact. Geometry did not come here to negotiate.
So we only care about adjacent pairs. Define
The constraints become
and pair is tangent iff
So the problem is now purely one-dimensional: maximize the number of tight adjacent inequalities.
Possible Radii After A Prefix
After processing gaps , we are standing at disk . For each , define as the set of possible values of if we can already achieve at least tangencies in the processed prefix.
These sets are open intervals. Suppose one such interval is
Now process the next gap .
If we make the next edge tangent, then
where is the old radius and is the next radius. We need , so the image interval is
If we do not force this edge to be tangent, we only need
Since can approach , the possible next radii are
The open endpoints matter. If , then no positive next radius fits. This is why the code uses strict , not .
The Greedy Invariant
The huge simplification is this invariant:
After each processed gap, let be the maximum achievable number of tangencies. Then:
In plain English: every non-best count is fully flexible. Only the current best count has a weird restricted interval.
Why is that true? If you are not chasing the absolute best count, you have at least one missed tangency available somewhere, and that missed edge lets you reset the next radius to basically anything positive below the current gap. The interval transition above makes this formal.
Now process a new gap .
Case 1:
Some best-count configuration has current radius small enough to fit through this gap. So we make this edge tangent and increase the answer:
The new best interval is the tangent image of :
Case 2:
Every best-count configuration has current radius too large. It cannot even satisfy
with . So the best state dies here. Brutal, but useful.
We fall back to the second-best state. By the invariant, its possible current radii are exactly
where is the previous gap. We make the new edge tangent, so the answer stays , and the new best interval is
That is the whole algorithm.
Why This Is Correct
The geometry lemma proves that every tangent pair must be adjacent, so maximizing tangent disk pairs is exactly maximizing tight constraints .
The interval transition is exact: from an old radius interval, either we make the next edge tight and reflect the interval through , or we leave slack and can choose any smaller positive next radius.
The invariant says we never need to store all . All counts below the best remain completely flexible over the latest gap, while the best count is summarized by one interval . The two update cases cover everything:
Thus the greedy update always preserves the true maximum after each prefix.
Complexity
Each gap is processed once. Total complexity is
per test case, with extra memory besides the input. Across all tests, this is , which is exactly what we need for points.
#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 INF = (1LL << 62);
while (T--) {
int n;
cin >> n;
vector<ll> x(n);
for (ll &v : x) cin >> v;
int ans = 0;
ll L = 0, U = INF;
ll prev = INF;
for (int i = 0; i + 1 < n; i++) {
ll d = x[i + 1] - x[i];
ll nL, nU;
if (L < d) {
ans++;
nL = max(0LL, d - U);
nU = d - L;
} else {
nL = max(0LL, d - prev);
nU = d;
}
L = nL;
U = nU;
prev = d;
}
cout << ans << '\n';
}
}#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 INF = (1LL << 62);
while (T--) {
int n;
cin >> n;
vector<ll> x(n);
for (ll &v : x) cin >> v;
int ans = 0;
ll L = 0, U = INF;
ll prev = INF;
for (int i = 0; i + 1 < n; i++) {
ll d = x[i + 1] - x[i];
ll nL, nU;
if (L < d) {
ans++;
nL = max(0LL, d - U);
nU = d - L;
} else {
nL = max(0LL, d - prev);
nU = d;
}
L = nL;
U = nU;
prev = d;
}
cout << ans << '\n';
}
}