Codeforces VP/补题小记
1149 C. Tree Generator
给你一棵树的括号序列,每次交换两个括号,维护每次交换之后的直径。
考虑括号序列维护树的路径信息和,是将左括号看做 \(-1\) ,右括号看做 \(1\) ,那么一段竖直向上的路径可以表示为括号序列的一个区间和,一段竖直向下的路径可以看做括号序列的一个区间和的相反数。我们要维护的是树的直径,也就是一段连续的和减去紧随其后的一段连续的差。具体来说就是
\[
\max_{\forall [l,r]}\{\sum_{i=l}^kw[i]-\sum_{i=k+1}^r w[i]\}
\]
可以简单的证明如果选取的区间不能代表树上的路径,取到的式子的和一定不是最优解,线段树维护这个式子即可。维护起来略有麻烦,类似于维护区间最大子段和,更新的时候需要多记几个信息。复杂度 \(\mathcal O (n\log n)\) 。
1149 D. Abandoning Roads
\(n\) 个点 \(m\) 条边且仅有两种边权 \(a, b (a<b)\) 的无向简单图 \(G\),\(\forall i\) 求出 \(G\) 的所有最小生成树中,\(1-i\) 的路径的最小长度。\(1\leq n\leq 70,n-1\leq m \leq 200\) 。
这个题我一开始想了一个错误的做法,先求出最小生成树中 \(b\) 边的数量记为 \(k\) ,然后分别求出 \(1\) 到各个点经过不超过 \(k\) 条 \(b\) 边的最短路。这个做法的错误之处在于,虽然可以证明起始端点都在路径上的 \(a\) 边不会环切掉路径上的 \(b\) 边,但是只要令始端点在路径上就能环切了。
期间我还考虑了另外一种做法,后来得知后一种思路是可以扩展到正解的。考虑将所有 \(a\) 边缩成若干个联通块,不难证明,如果一条生成树的路径离开了一个联通块后又进入了这个联通块,这棵生成树一定不是最小生成树,因为其选择了会被环切的 \(b\) 边。此时直接大力状压 \(dp\) 的复杂度是 \(O(2^nm)\) 的。
再往下分析,如果一个联通块大小 \(\leq 3\) ,那么即使存在离开这个联通块后又来到这个联通块的路径,这条路径也必然不是最短路,因为这样联通块内部最长的边是 \(2a\) ,而做上述操作需要 \(2b\) 。所以可以直接忽视掉所以大小 \(\leq 3\) 的联通块的限制,复杂度优化到 \(\mathcal O (2^{\frac{n}{4}}m)\)。
1168 C. And Reachability
有一个长度为 \(n\) 的序列 \(A\) , \(i,j\) 之间有一条有向边当且仅当 \(i < j, A[i] \text{ and } A[j] > 0\) ,每次给出 \(x, y(x<y)\) ,询问从 \(x\) 出发是否能到达 \(y\) 。
按位考虑,对于当前数 \(A[x]\) ,其能直接到达后面所有和其有共同位的数。显然,对于每一位,较前面的数能到达较后面的数,所以只需要维护每一个数 \(A[x]\) 其能到达某一位有 \(1\) 的最前面的数的位置即可。最后判断 \(A[y]\) 的某一位 \(1\) 是否能被 \(A[x]\) 在其之前到达。复杂度 \(\mathcal O(n\log^2 n)\) 。
1168 D. Anagram Paths
有一棵二叉树,每条边上有小写字母或者 \('?'\) ,每次修改一条边上的字符,要求维护所有叶子到根的路径上的 \('?'\) 填为任意小写字母后是否能重排达到一致, 如果可以,还需输出每种字符的最大可能出现次数。
首先如果所有叶子深度不相等,无论怎么更改边上的字符都是无解。
然后令 \(f[x][c]\) 表示所有 \(x\) 子树内的叶子到 \(x\) 的路径上字符 \(c\) 的数量最大值,\(len[x]\) 表示 \(x\) 到叶子的距离。
我们可以归纳证明,能够重排达到一致当且仅当
\[
\forall x \sum_{c} f[x][c]\leq len[x]
\]
考虑当 \(x\) 是叶子时候,显然充要。对于任意非叶子节点 \(x\),假设其子树内所有点都满足条件,此时必要性显然。充分性考虑先将原先的所有路径排好,对于新加进来的边,如果是一条,则必然合法。如果是两条边,要满足式子必须改变的 \(f[x][c]\) 数量 \(<2\) ,此时另一边会有多出来的问号填上这个字符。
直接暴力维护 \(f[x][c]\) 复杂度是 \(O(nq)\) 的,但是之前的证明启发我们,对于只有一个孩子的节点,可以直接将该节点与孩子合并不影响答案。然后这里有一个二叉树的小套路,如果这样合并,二叉树的深度不超过 \(\mathcal O(\sqrt n)\) 。
证明,如果二叉树不存在只有一个儿子的节点,那么第 \(i\) 层的深度一定要大于第 \(i-1\) 层的深度,此时深度最多为 \(\mathcal O(\sqrt n)\) ,这样直接暴力修改 \(dp\) 值即可,复杂度 \(\mathcal O(q\sqrt n)\)。当然直接动态 \(dp\) 也是可以的。
1188 D. Make Equal
有一个序列 \(a\) ,每次可以花费 \(1\) 的代价将其中一个数加上 \(2\) 的幂次,求将所有数变成相等的数时所需的最少代价。
先将 \(a\) 从小到大排序,若我们将 \(a_n\) 最终加上了 \(S\) ,则 \(a_i\) 最终加上了 \(S+a_n-a_i\) 。那么问题转化为选择一个数 \(S\) ,最小化 \(\sum_{i=1}^n bit(S+a_n-a_i)\) 。
考虑按位 \(dp\) 决策 \(S\) 的每一位选 \(0\) 还是选 \(1\) ,因为最终要处理的贡献是等于 \(a_n-a_i, S\) 这一位数相加以及上一位的进位决定的,我们还需要记录哪些数在当前状态下被进位了。可以发现,假设考虑到了前 \(k\) 位,当前位会进位的数一定是按照 \(\mod 2^k\) 排序结果下的一个后缀,\(dp\) 的时候记录一下这个后缀的长度即可,复杂度 \(\mathcal O (n\log n)\) 。
1098 D. Eels
鱼缸里有一些鱼,鱼有一个属性值 \(w_i\) ,两条鱼 \(i,j(w_i < w_j)\) 可能会合并为一条新的鱼 \(w_i+w_j\) ,如果一次合并的过程中有 \(2w_i\geq w_j\) ,那么称这一次合并是危险的。现在要动态加入删除鱼,维护如果开始一系列的合并,最多可能发生的危险合并次数。
打表发现发生危险合并最多的方式一定是每次取出当前两条最小的鱼进行合并,然后考虑怎么维护这个东西。考虑将当前所有鱼按照 \(w_i\) 排好序,当一条鱼满足 \(w_i > 2\sum_{j=1}^{i-1} w_j\) 时,这条鱼被取出的时候显然不会发生危险的合并。现在我们证明,除此之外的所有鱼被取出的时候,都会发生危险的合并。反证,假设取出的是两条鱼 \(x=w_a+w_b,y=w_c+w_d(2x< y)\) ,即 \(w_a+w_b<w_d\) ,也就是说 \(x\) 会先与 \(w_c\) 合并,不存在这样的两条鱼。那么我们只要动态维护
\[
\sum_{i=1}^{n}[w_i > 2\sum_{j=1}^{i-1} w_j]
\]
用一个维护权值时候的小技巧,将其划分成 \(\log\) 个块,第 \(i\) 个维护权值在 \([2^{i-1},2^i)\) 间的所有鱼,此时,每个块内只有最小值可能产生贡献,用堆来维护这个最小值可以做到 \(\mathcal O(n\log n )\) 的复杂度。
1083 C. Max Mex
有一棵树,树上的节点权值是一个 \(0\) 到 \(n-1\) 的排列,现在动态交换两个节点的权值,要求维护树上所有路径的 \(\text{mex}\) 的最大值。
假设答案是 \(k\) ,那么其合法的充要条件是 \(0-1,1-2,..,(k-1)-k\) 这些路径组成的并仍然是一条路径,我们用线段树维护一个区间内的路径的并的端点,然后在线段树上二分答案,预处理 \(lca\) 复杂度为 \(\mathcal O(n\log n)\) 。
1158 D. Winding polygonal line
平面上有 \(n\) 个点,要求找一个排列,满足相邻连线后不自交,且用一个字符串限制了第 \(i\) 步必须要左转/右转。\(n \leq 2000\) ,保证不存在三点共线的情况。
考虑每次找出在凸包上的任意一个点,其下一个点选择在凸包上左边/右边的点,剩下的点仍然组成一个凸包,且根据凸包的性质,之前选择的点一定不再剩下的点组成的凸包内,这样子分步构造即可,复杂度 \(\mathcal O(n^2)\)。
704 D. Captain America
平面上有 \(n\) 个点,每个点必须涂成红色和蓝色中的一种,花费各为 \(r\) 和 \(b\) 。需要满足 \(m\) 条限制,每条限制形如 \(y=b\) 这条直线上两种颜色的点的数目之差的绝对值不能超过 \(d\) 或 \(x=b\) 这条直线上两种颜色的点的数目之差的绝对值不能超过 \(d\),要求判断是否有解,如果有解还需要最小化花费。\(n,m \leq 10^5\) 。
先考虑判断是否有解, 假设某一行的限制为 \(d\) ,一共有 \(k\) 个点,选了 \(x\) 个红点,满足条件即
\[
|2x-k|\leq d \\
-d \leq 2x-k \leq d \\
\dfrac{k-d}{2}\leq x \leq \dfrac{k+d}{2}
\]
对于列的限制同理,考虑经典的二分图建模,每一个点选红色就让对应行的点和对应列的点连边,那么源点连向行的边和列连向汇点的边就是上面的上下界限制,存在可行流即有解。最小化花费即最大化花费较小的那种颜色的点数,在可行流基础上跑最大流即可。