做贺了一下,作文以记之。
-
-
题意:
直观描述一下:就是 \(M\) 个人,可以涂一些特定颜色的墙,看成一个环,可以从任意处断开成 \(M\) 个数的数列。 有 \(N\) 个面的墙,对于一连续段长度为 \(M\) 的面,如果 \(M\) 个人可以依次涂这些墙,就代表这一次刷墙是合法的。求最小刷墙次数。
-
能发现区间的长度是固定的,任意区间的关系只有相交或分离,求最小覆盖次数,这里面有类似单调性的玩意,这样就很容易有贪心的算法, 类似的有 P4155 [SCOI2015]国旗计划。
-
问题在于求哪些区间合法。
一开始一直在想暴力 bitset。其实题目限制埋伏了一手,经过一些推导,发现每一面墙最大只有 \(700\) 个人能涂。
考虑dp,状态是 \(f_{i, j}\) 第 \(i\) 面墙到 第 \(j\) 个人的时候最多涂了多少墙,能发现状态是 \(N \times M\), 转移时就能利用这个条件优化,空间上就用滚动数组优化。
-
-
-
题意:
连通图,两点相互到达各自的点,不能相遇,不是同时走(其中一个点可以不动),每个询问求经过的边的最大值最小。
-
首先有想法按照小到大将边加入,再判断能否相互到达,不过这样没有什么前途,虽说有单调性,但整体二分好像做不了。
-
其实感觉这种题就是要推充要条件,实际上,两点能相互到达当且仅当两点所在连通块不是一条链。大概就是链的话一定会相遇,如果多出来一个点,那么让一个点暂时待在这个点,等到另一个点路过这个点,再让它出来。
-
剩下的问题就是判断连通块是不是链,和解决最大值最小,这时就能想到kruskal重构树,它可以同时解决连通性相关和边权最小/大值的一些问题。按照小到大进行建树即可,维护连通块是不是链应该不是很难,还有一些建树的小问题。最后树上lca即可。
-
-
-
题意:
给出 \(N\), 表示这是 \(N\) 个点的二叉树。
可以询问两点距离和能支配的点的个数。
在 \(4 \times 10^5\) 次询问内,求出 \(N\) 个元素排列 \(p\), 满足任意 \(i > 2\), \(\text{dis}(p_i, p_{i - 1}) \geq \text{dis}(p_{i - 1}, p_{i - 2})\),即随着 \(i\) 变大,两点的距离不升。
-
实际上没有啥算法能在 \(4N\) 次询问内求出原树,求出树的直径也没事好的想法。
-
考虑重心,假如求出重心 \(r\), 它只有两个儿子,那么大小一定分别为 \(\lfloor\frac{n}{2}\rfloor, \lceil\frac{n}{2}\rceil\), 这时只用从较大的子树开始,轮流取深度最大的点,可以发现这样一定满足题意。
-
如果他有三个儿子,这时就要分类讨论了。
-
加入最大的子树大小等于其余两个子树的和,将两个子树合并,按时上面方法即可。
-
加入最大的子树大小小于其余两个子树的和, 每次在和上一个子树不同的子树内取深度最大的点,总会存在加入最大的子树大小等于其余两个子树的和的情况,这时就可以采用上面的方法。
但是还要考虑上一次选的子树,来决定这时从哪里开始。
还有一种特殊情况,假如上一次选的是合并两个子树中的某一个,另一个子树最大深度比大小最大的子树的最大深度大,要再次选回合并两个子树的另一个。
-
加入最大的子树大小大于其余两个子树的和, 由于重心的定义,这里最大出现大于 \(1\), 在先在最大子树内取一个即可。
-
找重心:
- 在所有 \(n - siz_i <= \frac{n}{2}\) 并且 \(siz_i\) 最小的点是重心。
考虑以点 \(u\) 为根,而实际上的重心为 \(v\)。
那么只有 \(u,v\) 之间的路径上的点的 \(siz\) 大于 \(\frac{n}{2}\)。
而 \(siz\) 从浅到深递减,故 \(siz \geq \frac{n}{2}\) 且最小的那个,即为 \(u,v\) 之间路径的最低点: 重心 \(v\)。
------ command_block所以以 \(0\) 为根,求出每个点的子树的大小,按照上面的方法在 \(n\) 次询问求出。
-
求每个点到重心的距离 花费 \(n\) 次。
-
求每个点在哪个子树,如果有重心三个儿子,不在第一第二个,就一定在第三个,所以最多两次询问,花费 \(2n\) 次。
-
总结一下吧:
-
题目限制很重要。
-
都是交互题的形式,会用交互了,多写能试出平常难以发现的错误, cerr是个好东西。
-
对于判定合法问题,最好找充要条件,一般来说不会很复杂。
-
有关树的交互题,一般都是利用树的直径,重心的性质,按照一定的贪心策略。
-
分类讨论很重要,一步一步思考清楚,老是因为分类讨论出小错误挂,上次 div2 就是这样(好像每次都是这样)。