为了监督自己做题时写思路以集中注意力,从而提高效率,同时简单记录解法,防止以后看不懂自己代码特开此文。

只记录简单做法,为防止长度过长加载速度慢,所以就不贴代码了,反正到处都存了

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