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 of every detected moment as either +1 (someone enters) or -1 (someone exits). The total stay time is not about individual identities; it is the area under the number-of-people-inside curve.
Between and , the number of people inside is constant. If the height after processing event is , the contribution is .
For a fixed , the best height path starts at , ends at , uses steps , never goes below , never exceeds , and wants to spend as much weighted time as possible at high height.
Split the timeline into blocks of events. Inside each full block, the best possible shape is forced: climb during the first events, then fall during the next events. Any delay in climbing or early descent only loses positive gap lengths.
So for each , sum the value of every full -event “mountain”, plus one possible leftover mountain of height if the remaining suffix has events. Precompute prefix sums of times so each mountain value is just sum(second half) - sum(first half).
Let’s translate the story into the thing it actually is.
At every detected time, exactly one person crosses the door. If they enter, the number of people inside goes up by . If they exit, it goes down by .
The museum starts empty and ends empty, so over the events we need a sequence of ups and downs. Also, for a given limit , the height must always stay between and .
The total stay time is the area under this height curve. If is the number of people inside after event , then during the whole interval that number is constant, so the score is
Same problem, less museum cosplay: build the highest possible valid mountain path.
Key greedy shape
Take any chunk of consecutive events, starting when the museum is empty.
With capacity , the best thing is obvious once you stop overthinking it:
That means:
Why? All gaps have positive length. Higher occupancy over any gap is always better. So you want to climb as fast as possible until hitting , then stay as high as the step rules allow, and only descend when you must in order to finish the block. Delaying an entrance is just throwing away positive area for no reason. Classic greedy: don’t make the height curve lower if you can legally make it higher.
The value of such a block covering events
is exactly
That is because those first times become entries, and those next times become exits.
What about all events?
For a fixed , repeat full mountains of size from left to right:
If there are leftover events, the count must be even because the total is . Say the leftover size is , where . Then the final chunk uses a smaller mountain of height :
So the answer for is the sum of block values over these chunks.
This might look slightly suspicious: why are we allowed to reset to after every block? Could keeping people inside across a boundary help?
No. The greedy mountain over each prefix is already lexicographically as high as possible under the cap and the need to return eventually. Another way to say it: in any consecutive events, once you start at , you cannot get more than the mountain area of height . Crossing block boundaries would force some earlier height to be lower or some later descent to happen sooner. Since every gap length is positive, that trade is never useful. The fastest-climb, latest-drop pattern dominates.
Fast computation
Define prefix sums:
Then the value of a block starting at 0-based index l with half-size len is
With prefix sums, that is .
For each :
0.2*k events remain, add a full block of half-size k.2*r events remain, add one final block of half-size r.The harmonic-looking loop is fine:
Across all tests, , so this cruises.
Complexity
For one test case, the total work over all is , and memory is .
Use long long; answers can be around , so int will faceplant.
#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--) {
int n;
cin >> n;
int m = 2 * n;
vector<ll> a(m), pref(m + 1, 0);
for (int i = 0; i < m; i++) {
cin >> a[i];
pref[i + 1] = pref[i] + a[i];
}
auto blockValue = [&](int l, int len) -> ll {
if (len == 0) return 0;
ll first = pref[l + len] - pref[l];
ll second = pref[l + 2 * len] - pref[l + len];
return second - first;
};
for (int k = 1; k <= n; k++) {
ll ans = 0;
int pos = 0;
while (pos + 2 * k <= m) {
ans += blockValue(pos, k);
pos += 2 * k;
}
int rem = m - pos;
ans += blockValue(pos, rem / 2);
cout << ans << (k == n ? '\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;
while (T--) {
int n;
cin >> n;
int m = 2 * n;
vector<ll> a(m), pref(m + 1, 0);
for (int i = 0; i < m; i++) {
cin >> a[i];
pref[i + 1] = pref[i] + a[i];
}
auto blockValue = [&](int l, int len) -> ll {
if (len == 0) return 0;
ll first = pref[l + len] - pref[l];
ll second = pref[l + 2 * len] - pref[l + len];
return second - first;
};
for (int k = 1; k <= n; k++) {
ll ans = 0;
int pos = 0;
while (pos + 2 * k <= m) {
ans += blockValue(pos, k);
pos += 2 * k;
}
int rem = m - pos;
ans += blockValue(pos, rem / 2);
cout << ans << (k == n ? '\n' : ' ');
}
}
return 0;
}