Codeforces Round #441 (Div. 1, by Moscow Team Olympiad) 题解

A - Classroom Watch

考虑给定值是 \(x+y\),原来的值为 \(x\),那么显然 \(y\)\(100\) 之内。暴力枚举即可。

B - Sorting the Coins

考虑一个局面对应的答案,等价于最后一个 O 前面 X 的个数 \(+1\)​。树状数组可以直接维护。对应最后一个 O 的位置维护可以 std::set,也可以倒着做。做的时候因为读题 + 没想清楚浪费了很多时间。复杂度 \(O(n\log n)\),应该可以 \(O(n)\)

C - National Property

对于一个 \(i\in[1, n)\)​​,如果 \(s_{i}\) 不是 \(s_{i+1}\) 的前缀,那么必然存在一个 \(k\) 满足 \(s_{i,k}\ne s_{i+1,k}\) 并且第 \(k\) 位之前全部相等,或者说我们必须​造出这样一个 \(k\)

具体而言,如果 \(s_{i,k}\ne s_{i+1,k}\),那么有:

  • \(s_{i,k}>s_{i+1,k}\):这时需要靠改掉 \(s_{i,k}\) 扭转乾坤。
  • \(s_{i,k}<s_{i+1,k}\)​:那么我们需要维持现状,如果说 \(s_{i+1,k}\)​ 被改了,那 \(s_{i,k}\)​​ 也应该被改,保持原有的大小关系。然而做的时候被我漏了。

然而有一点瑕疵:倘若在 \(s_{i,k}>s_{i+1,k}\) 情况中不仅改了 \(s_{i,k}\) 还改了 \(s_{i+1,k}\),怎么办?有两种解决方案,第一种比较直接,套用 2-SAT 模型即可,“改”与“不改”分别作为 \(0,1\)。或者是采用第二种,相对简单,只要对第二种情况建图,\(s_{i,k}\to s_{i+1,k}\),当 \(u\to v\) 的有向路径存在时,如果 \(u\) 被改了,那 \(v\) 也改。最后检查一边合不合法就行了。复杂度都是 \(O(n)\)。​

D - High Cry

考虑对于每个 \(i\),计算以位置 \(i\) 作为最大值的所有包含 \(i\) 的区间中,不合法的个数。那么这个区间 \([l,r]\) 应满足:

  • \(i\in [l,r], \max_{j=l}^r a_j=a_i\)
  • \(\forall j\in [l,r], a_i \text{ or } a_j=a_i\)。​

第一个显然,第二个也不难理解:不合法的必然是最大值等与区间或值。单调栈计算第一个限制的边界,开个 \(\log a\) 大小的桶计算第二个限制的边界。总复杂度 \(O(n\log a)\)

E - Delivery Club

二分答案是显然的。思考对于一个答案 \(K\) 如何判定合法性。

考虑一个 dp:\(f_t(i,j)\)​​​ 表示送完包裹 \(t\)​​,一个人在位置 \(i\)​​​,另一个在 \(j\)​​​​ 是否可能。然后有一个非常简单的优化:必然有一个人在 \(x_t\) 处,这样可以省掉一个维度。

整个 dp 数组不难维护,线段树即可。写完才发现可以用 std::set 直接维护 dp 值为 \(1\) 的位置,更加方便,亏大了。复杂度 \(O(n\log n\log x)\)

F - Royal Questions

没想到,但是想到了思维深度其实也不大。考虑一个很神奇的图论模型:对于一个 \((a,b,w)\) 的公主抽象成一条无向边,那么王子就是点。最后我们选 \(k\) 个点 \(k\) 条边,并且对应的图联通。不难发现这样最终可以匹配上。

发现上面的条件实际上就是基环树!那么套用 Kruskal 生成树算法,外加记录一个连通块中是否有环,合并时随便维护一下就行了。复杂度 \(O(n\log n)\)

posted @ 2021-08-15 21:59  -Wallace-  阅读(104)  评论(0编辑  收藏  举报