「CEOI2011」选做

Teams

\(\mathcal{O}(n\log n)\) 是一个平凡的二分,来一发 \(\mathcal{O}(n)\) 的奇妙解法。

对于第一问,设 \(F_i\) 表示前 \(i\) 个小朋友能分成的最大队伍数。

为保证无后效性并创造单调性质,需要将 \(a_i\) 降序排序,易证。

考虑不同转移的情况,发现转移 \(F_i \gets F_{j} + 1\) ,当且仅当 \(a_j + j = i\)

还有一个平凡的转移 \(F_i \gets F_{i-1}\) ,总转移数是 \(\mathcal{O}(n)\) 级别的。

第二问,最小化最大队伍的人数,设 \(G_i\) ,表示前 \(i\) 个小朋友最大队伍的人数。

对于 \(F\) 的平凡转移,只需要考虑一人新加进来的情况,判断前一状态是否满足被分的所有组别都达到了最大人数,表达式:

\[G_i \gets G_{i-1} + [G_{i-1} * F_{i-1} = i - 1] \]

对于另一种转移,新加进了一个队伍,显然有转移:

\[G_i \gets \max\{ G_j , i - j\} \]

由于是构造题,只需要记录每次新加队伍的区间即可,即在第二种转移时记录下标 \(j\)

Code(C++): Link

Matching

将整个排列转化为每个值前面有几个比它大的数,可以证明对于任意一个顺序确定的序列,这样的转化是唯一的。

随后用 BIT 维护,用 KMP 算法匹配即可。

Code(C++): Link

Treasure Hunt

由于有加点操作,只能用倍增维护。

考虑 \(50\%\) 的数据,对于询问操作列出步骤。

先找到 LCA ,求出 \(u\rightarrow v\) 的长度为 \(\text{dist}\) ,找出更深的一条树链,若这是 \(rt \rightarrow u\) 则记 \(d = \lfloor \frac{dist}{2}\rfloor\) ,否则记 \(d = \lceil \frac{dist}{2} \rceil\)

根据 \(d\) 向上倍增找点即可。

对于 \(100\%\) 的数据,发现难点在如何判断一段节点到另一段节点后出现的位置,将此也倍增维护即可。

Code(C++) : Link

posted @ 2021-03-08 13:12  AxDea  阅读(96)  评论(0编辑  收藏  举报