为了监督自己做题时写思路以集中注意力,从而提高效率,同时简单记录解法,防止以后看不懂自己代码特开此文。
只记录简单做法,为防止长度过长加载速度慢,所以就不贴代码了,反正到处都存了。
CF1059E Split the Tree
简单 2400 的题,做题时比较浮躁,静不下来,做了比较久。
考虑到每个点必然包含在一条垂直路径,根节点必然是垂直路径的顶端。
定义 f[i] 表示以 i 号点为垂直路径顶端点,i 的子树内的节点全覆盖的最少垂直路径数量。
显然满足
\(\sum_{v \in son_x} f_v\) <= f_x <= \(\sum_{v \in son_x} f_v\) + 1 即要么单飞,要么与下面某条路径合并
转移即判断能否找到一个单飞转移点与当前点形成路径满足条件。
由此可知,单飞的越晚越优,即能不单飞就不单飞,既把单飞机会留给之后使转移更多,又让当前位置答案更小
由此发现,当答案最优时,单飞与否的状态也是不劣的
明显,当确定一个点单飞后,做一个差分维护是否单飞
可以倍增解决。
复杂度 \(O(n \log n)\)
[清北学堂] 校门外的树
研究标程把这道题弄明白了,于是来写一篇题解。
题意:
询问一个区间内的元素的最小差值。
分析本题,发现能够对答案产生贡献的数对具有 \(n^2\) 个,但是其中存在大量的无用的数对状态。
举个例子,对于点 \(i,j\) ,满足 \(h_i < h_j\) ,则发现满足 \(k > j , h_j < h_k\) 的 \(k\) ,都是无法与 \(i\) 对任何一个区间的答案产生贡献的。因为他离 \(i\) 比 \(j\) 远,又没有 \(j\) 贡献答案优秀。
类似地,我们考虑能否进一步减少我们的有用的数对数量。
考虑 \(k>j , h_k < h_j\) ,发现这样的一些 \(k\) 并不完全可能与 \(i\) 产生贡献,因为这些数有可能与 \(j\) 组成数对会答案产生更优秀的贡献。
简单分析可以发现,当 \(h_k < (h_j + h_i) / 2\) 时,\(i,k\) 才不一定劣。
按照上述分析不断迭代下去,容易发现,对于每个 \(i\) ,最只有 \(\log M\) 个(\(M\) 为值域) \(j\) 满足 \(j > i\) 且与 \(i\) 组成数对不一定劣。
同理对 \(j > i , h_j < h_i\) 的 \(j\) 寻找不一定劣的数对。
因此有用的数对个数就被压缩到了 \(\log M\)(\(M\) 为值域) 对。
考虑寻找这些数对。只用开一棵动态开点线段树从后往前扫一遍,每次寻找满足不一定劣值域范围的最近的位置就好了。
找到数对后,离线询问,左端点从大到小排序扫一遍,求符合范围的数对权值最小值,用树状数组维护一下就好了。
CF1451F Nullify The Matrix
显然这是一场会结束的游戏,因为路径总是从左上角到右下角,而开头总会减去正整数
考虑使用 SG 函数来分析
考虑类比 Nim 游戏,按照一定规则分类,将异或值做权。
若所有类的值不全为 0 且先手总是可以将所有类变为 0 则先手必胜。
对于初格,只能减,则只要找到包含该类二进制最高位元素即可
对于非初格,任意元素均可实现
发现按左斜线分类恰能满足
CF1451E Bitwise Queries
询问 n - 1 次,我们可以知道任意两个元素之间的异或值
通过知道任意两个数的 & 值,我们就可以求出他们的 | 值
((\(x_1\) | \(x_2\)) & (\(x_2\) | \(x_3\))) ^ (\(x_1\) & \(x_3\)) ^ (\(x_1\) & \(x_2\) & \(x_3\)) = \(x_2\)
n + 2 次
E1 solved
显然,要么 a 是排列 , 要么存在两个元素相同
若存在两个元素相同,& 运算求得,然后异或带回即可。
若 a 是排列 , 则必然有 x_1 ^ x_i = n - 1 的位置 , 任选一个 x_j
\(x_2\) = (\(x_1\) | \(x_2\)) & (\(x_2\) | \(x_3\))
E2 solved