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 in terms of crash segments. After a crash, the array is exactly the original array again, so everything before that crash is dead history.
Only one position changes in each operation. Since all , a crash after operation can only be caused by the updated index .
Inside one segment after the most recent crash, index has value
where the sum is over operations in the current segment with . If this exceeds , the whole segment gets wiped.
Do not actually reset all values on every crash. That is the obvious trap, and it gets smoked if many operations crash.
Use a lazy reset with a segment/version counter. Store for each index the version when its current value was last initialized. When the global version increases after a crash, old stored values are treated as stale and lazily replaced by the original the next time that index is touched.
The main thing to notice is that a crash does not partially undo anything. It nukes the entire current history and restores the original array.
So at any moment, the only operations that matter are the operations since the most recent crash. Call that current block a segment.
For an index , during the current segment its value is
Since every , values never decrease inside a segment. Also, each operation changes exactly one element, so after applying operation , the only element that could newly become greater than is . No need to scan the whole array. Scanning would be silly. Resetting the whole array every crash would be worse: that is how you manufacture your own TLE.
The direct simulation idea is:
The only annoying part is step 3. There may be crashes, and resetting all elements each time would be in the worst case.
Instead, use a lazy reset.
Maintain:
orig[i]: the original value .cur[i]: the currently stored value for index .seen[i]: the segment/version where cur[i] is valid.ver: the current segment number.Initially ver = 1. Before using index , check whether seen[x] == ver.
If not, then cur[x] belongs to an old segment and is garbage for the current one. Reinitialize it lazily:
Then set seen[x] = ver.
Now process the update:
If cur[x] > h, the computer crashes. We do not reset arrays manually. We simply increment ver. From now on, every old cur[i] automatically becomes stale because its seen[i] is from an older version.
At the end, the final value of index is:
cur[i] if seen[i] == ver, because it was touched in the final segment;orig[i], because it has not been changed since the last crash.Why this works:
The invariant is that for every index with seen[i] == ver, cur[i] equals the actual value of in the current segment. For every other index, the actual value is just orig[i], because it has not been initialized or touched since the latest crash.
Before an update, we lazily restore the target index if needed, so the invariant holds for that index. Then we add , matching the operation exactly. If the result is at most , no crash happens and the invariant continues to hold.
If the result is greater than , a crash resets every element to orig. Incrementing ver makes all previously stored values stale at once, which is exactly equivalent to resetting the whole array, except we spend instead of doing the clown-car reset.
Edge cases:
ver just keeps increasing and the final output is the original array.long long, because sums can reach about .Complexity per test case is
time and
memory. Across all test cases, this fits easily because the total and total are bounded by .
#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, m;
ll h;
cin >> n >> m >> h;
vector<ll> orig(n + 1), cur(n + 1);
vector<int> seen(n + 1, 0);
for (int i = 1; i <= n; i++) cin >> orig[i];
int ver = 1;
for (int i = 0; i < m; i++) {
int b;
ll c;
cin >> b >> c;
if (seen[b] != ver) {
seen[b] = ver;
cur[b] = orig[b];
}
cur[b] += c;
if (cur[b] > h) {
ver++;
}
}
for (int i = 1; i <= n; i++) {
ll ans = (seen[i] == ver ? cur[i] : orig[i]);
cout << ans << ' ';
}
cout << '\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, m;
ll h;
cin >> n >> m >> h;
vector<ll> orig(n + 1), cur(n + 1);
vector<int> seen(n + 1, 0);
for (int i = 1; i <= n; i++) cin >> orig[i];
int ver = 1;
for (int i = 0; i < m; i++) {
int b;
ll c;
cin >> b >> c;
if (seen[b] != ver) {
seen[b] = ver;
cur[b] = orig[b];
}
cur[b] += c;
if (cur[b] > h) {
ver++;
}
}
for (int i = 1; i <= n; i++) {
ll ans = (seen[i] == ver ? cur[i] : orig[i]);
cout << ans << ' ';
}
cout << '\n';
}
return 0;
}