题解 P10055【[CCO2022] Rainy Markets】
首先尽量把所有人放在左边的车站,然后再尽量放在右边的车站,求出此时 \(i\) 位置车站有多少空位留给 \(i+0.5\) 位置的人,记为 \(f_i\)。也就是:
\[f_i\gets\max\{b_i-\max\{p_{i-1}-f_{i-1},0\},0\}
\]
然后从右向左贪心。对于第 \(i+0.5\) 位置的人,设去左边、不动买伞、去右边的人数分别为 \(l_i,m_i,r_i\)。由于右侧都已经尽量优地分配过,令这个位置的人优先去右边不会使得情况变得更劣,因此先贪心把右边填满,也就是:
\[\begin{aligned}
r_i&\gets\min\{b_{i+1}-l_{i+1},p_i\}\\
p_i&\stackrel{-}{\gets}r_i
\end{aligned}
\]
之后为了使总花费尽量小,肯定是在不影响左侧的情况下尽量都去左边,这时候计算过的 \(f_i\) 就派上了用场,\(f_i\) 就代表着左边有多少地方一定可以给 \(i+0.5\) 位置的人,且不会影响左侧的决策,也就是:
\[\begin{aligned}
l_i&\gets\min\{f_i,p_i\}\\
p_i&\stackrel{-}{\gets}l_i
\end{aligned}
\]
剩下的人一定需要买伞,因为即使在这里不买伞,去到左边也会使得左边的一些人需要买伞。我们让他们直接就地买伞:
\[\begin{aligned}
m_i&\gets\min\{u_i,p_i\}\\
p_i&\stackrel{-}{\gets}m_i\\
ans&\stackrel{+}{\gets}m_i
\end{aligned}
\]
如果还有剩下的人,就不得不让他们去左边挤一挤了:
\[l_i\stackrel{+}{\gets}p_i
\]
如果 \(l_i > b_i\) 即为无解,所有 \(l_i\le b_i\) 即求得了最优解及其构造。
时间复杂度 \(O(n)\)。
所有关键都在上文给出了,代码就不放了。