F - Falling Bars 解説 by en_translator
We assume that \(R_1 \geq R_2\geq \dots \geq R_N\).
First of all, we can safely ignore bars \(j\ (j > i)\) when determining the final position of bar \(i\) (because the bars that are initially above bar \(i\) never end up below bar \(i\)). Thus, we may consider the last position of bar \(i\) for \(i=1,2,\dots,N\), one by one.
Let us consider how to find the final position of some bar \(a\ (1\leq a\leq N)\) when that of bars \(i\ (i < a)\) are already known.
For each \(1\leq j\leq W\), let \(m_j\) be the row index of the topmost cell in column \(j\) that is occupied by one of bars \(1,2,\dots,a-1\) after sufficient time (or \(H+1\) if none of the cells in the column is occupied).
Then, we can prove that the row \(R'_a\) at which bar \(a\) will end up after sufficient time is \(\min\{m_j: C_a \leq j < C_a+L_a\}-1\).
Once you have found the final row of bar \(a\), we need to appropriately update the values \(m_j\) to find the final positions of bars \(a+1,a+2,\dots\). Specifically, we need to set \(m_j\) to \(R'_a\) for each \(j\ (C_a \leq j < C_a+L_a)\).
In summary, it is sufficient to do the following process fast:
- Initialize as \(m_1=m_2=\dots=m_W=H+1\).
- For \(i=1,2,\dots,N\), do the following:
- Let \(R'_i\leftarrow \min\{m_j: C_i \leq j < C_i+L_i\}-1\).
- For each \(j\ (C_i \leq j < C_i+L_i)\), set \(m_j\leftarrow R'_i\).
This can be processed in a total of \(O(W+N\log W)\) 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';
}
}
投稿日時:
最終更新: