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 simulate soldiers. The final occupied bases can be treated as some nearest bases to the left of , some nearest bases to the right of , plus itself. Farther bases are never cheaper than closer ones, shocking absolutely nobody.
Let be the number of fortified bases strictly left of , and strictly right of . Then the answer for this choice is . The real question is: how many days are needed for a chosen pair ?
For one side of length , the minimum is days: wait days to have soldiers at , then move a convoy outward for days, leaving one soldier behind at each base.
For both sides, the longer side is the bottleneck. If and , the minimum days are
Build the longer side first; while doing that, new soldiers pile up at , enough to build the shorter side afterward.
Binary search . For a fixed , we need some split within side capacities and with
That becomes a simple interval check for possible .
We start at base , and every day we get exactly one command before a new soldier appears at . The command can move a whole pile one step, which is the important trick. If you try to track every soldier individually, congrats, you have chosen pain.
Shape of the answer
Suppose we fortify some bases on the left of . If we can fortify a base at distance , then fortifying a base at distance is never harder. So for maximizing the count, we only care about how many bases we take on each side, not their exact identities.
So the final useful shape is:
The number of fortified bases is:
The side limits are:
Now we need to know when a pair is possible in days.
One side first
Say we only want bases on one side.
The optimal strategy is:
This takes:
days.
Why can't we do better? Because the farthest base needs a soldier moved outward times, and the bases behind it each need an extra soldier left behind. Sending one brave dude forward early just creates holes behind him, and then you pay to refill those holes later. No free lunch, just logistics being annoying.
Two sides
Now suppose we want bases on the left and on the right.
Let:
The longer side is the bottleneck. Build that side first using the one-side convoy idea. While that convoy is moving, new soldiers keep appearing at . Since the other side has length at most , enough soldiers are waiting at when we need them.
So the minimum number of days is:
This also covers the one-sided case. If , then it becomes:
If , the answer is just base , needing days.
Checking a fixed answer size
Let be the number of fortified bases outside .
We want to know if there is a valid split such that:
Rearrange:
Call this value:
Now must satisfy all of these:
So possible values form one interval:
If that interval is non-empty, then outside bases are possible.
Binary search
If we can fortify outside bases, then we can definitely fortify fewer. So feasibility is monotonic, and we binary search the maximum .
The final answer is:
because base is always fortified at the end of every day by the newly arriving soldier.
Complexity per test case:
That is easily fine.
#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;
while (t--) {
ll n, m, k;
cin >> n >> m >> k;
ll leftCap = k - 1;
ll rightCap = n - k;
auto ok = [&](ll d) -> bool {
if (d == 0) return true;
ll lim = m - d + 1; // need max(L, R) <= lim
if (lim < 0) return false;
ll low = max({0LL, d - rightCap, d - lim});
ll high = min({leftCap, d, lim});
return low <= high;
};
ll lo = 0, hi = min(n - 1, m);
while (lo < hi) {
ll mid = (lo + hi + 1) / 2;
if (ok(mid)) lo = mid;
else hi = mid - 1;
}
cout << lo + 1 << '\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;
while (t--) {
ll n, m, k;
cin >> n >> m >> k;
ll leftCap = k - 1;
ll rightCap = n - k;
auto ok = [&](ll d) -> bool {
if (d == 0) return true;
ll lim = m - d + 1; // need max(L, R) <= lim
if (lim < 0) return false;
ll low = max({0LL, d - rightCap, d - lim});
ll high = min({leftCap, d, lim});
return low <= high;
};
ll lo = 0, hi = min(n - 1, m);
while (lo < hi) {
ll mid = (lo + hi + 1) / 2;
if (ok(mid)) lo = mid;
else hi = mid - 1;
}
cout << lo + 1 << '\n';
}
}