F - Falling Bars Editorial by en_translator
We assume that .
First of all, we can safely ignore bars when determining the final position of bar (because the bars that are initially above bar never end up below bar ). Thus, we may consider the last position of bar for , one by one.
Let us consider how to find the final position of some bar when that of bars are already known.
For each , let be the row index of the topmost cell in column that is occupied by one of bars after sufficient time (or if none of the cells in the column is occupied).
Then, we can prove that the row at which bar will end up after sufficient time is .
Once you have found the final row of bar , we need to appropriately update the values to find the final positions of bars . Specifically, we need to set to for each .
In summary, it is sufficient to do the following process fast:
- Initialize as .
- For , do the following:
- Let .
- For each , set .
This can be processed in a total of time using a lazy segment tree allowing segment-min & segment-update, or segment-min & segment-chmin (chmin = change to the smaller value). Therefore, the problem has been solved.
Sample code (C++9:
#include <bits/stdc++.h>
#include <atcoder/lazysegtree>
using namespace std;
using namespace atcoder;
const int inf = 1e9;
using S = int;
using F = int;
S op(S l, S r) { return min(l, r); }
S e() { return inf; }
S mapping(F l, S r) { return min(l, r); }
F composition(F l, F r) { return min(l, r); }
F id() { return inf; }
int main() {
int h, w, n;
cin >> h >> w >> n;
vector<int> r(n), c(n), l(n);
for (int i = 0; i < n; i++) {
cin >> r[i] >> c[i] >> l[i];
--c[i];
}
vector<int> ord(n);
iota(ord.begin(), ord.end(), 0);
sort(ord.begin(), ord.end(), [&](int i, int j) { return r[i] > r[j]; });
vector<int> ans(n);
lazy_segtree<S, op, e, F, mapping, composition, id> seg(vector<int>(w, h + 1));
for (int i: ord) {
ans[i] = seg.prod(c[i], c[i] + l[i]) - 1;
seg.apply(c[i], c[i] + l[i], ans[i]);
}
for (int i = 0; i < n; i++) {
cout << ans[i] << '\n';
}
}
#include <bits/stdc++.h> #include <atcoder/lazysegtree> using namespace std; using namespace atcoder; const int inf = 1e9; using S = int; using F = int; S op(S l, S r) { return min(l, r); } S e() { return inf; } S mapping(F l, S r) { return min(l, r); } F composition(F l, F r) { return min(l, r); } F id() { return inf; } int main() { int h, w, n; cin >> h >> w >> n; vector<int> r(n), c(n), l(n); for (int i = 0; i < n; i++) { cin >> r[i] >> c[i] >> l[i]; --c[i]; } vector<int> ord(n); iota(ord.begin(), ord.end(), 0); sort(ord.begin(), ord.end(), [&](int i, int j) { return r[i] > r[j]; }); vector<int> ans(n); lazy_segtree<S, op, e, F, mapping, composition, id> seg(vector<int>(w, h + 1)); for (int i: ord) { ans[i] = seg.prod(c[i], c[i] + l[i]) - 1; seg.apply(c[i], c[i] + l[i], ans[i]); } for (int i = 0; i < n; i++) { cout << ans[i] << '\n'; } }
posted:
last update: