题解 P6198 【[EER1]单调栈】

xht

2020-03-11 14:11:36

Solution

本来不想写这题题解的,结果发现题解区全是带 $\log$ 的屑做法...... 贪心的过程很显然: 1. 若某个位置为 $-1$,把它设成前一个数的 $+1$ 即可。 2. 从区间 $[1,n]$ 开始递归处理。 3. 对于一个区间 $[l,r]$,用区间内最小的数将区间再划分为若干的个子区间。 4. 在最小的数所在的位置上,从右往左依次从小到大填数。 5. 从左往右依次处理每个子区间。 要证这个贪心,首先要证明这么做的正确性,然后证明没有更优解。 这两个证明都很 trivial,BF 的题解也有写,不是本文重点,略过。 本文的重点在于,BF 实现上面那个过程莫名其妙地用了一个 `set`。 可以线性为啥要带 $\log$,可以 `vector` 为啥要 `set`,屑( 这种题就应该出到 $10^7 \sim 10^8$ 卡死 $\log$( 没错,我写这个题解就是为了 diss BF 的( 另外,个人感觉这题也就是个 C,不知道为啥能放 E 去( ```cpp const int N = 1e6 + 7; int n, a[N], ans[N], t, cnt; vi p[N], q; void solve(int l, int r, int o) { if (l > r) return; for (int i = p[o].size() - 1; ~i; i--) if (p[o][i] <= r) q.pb(p[o][i]); else break; while (q.size()) ans[q.back()] = ++t, q.pop_back(); solve(l, p[o].back() - 1, o + 1); int x = p[o].back(); p[o].pop_back(); while (p[o].size() && p[o].back() <= r) solve(x + 1, p[o].back() - 1, o + 1), x = p[o].back(), p[o].pop_back(); solve(x + 1, r, o + 1); } int main() { rd(n), rda(a, n); for (int i = 1; i <= n; i++) if (!~a[i]) a[i] = a[i-1] + 1; for (int i = n; i; i--) p[a[i]].pb(i); solve(1, n, 1); for (int i = 1; i <= n; i++) print(ans[i], " \n"[i==n]); return 0; } ```