例 1. \(\text{CF1054E Chips Puzzle}\)
题目并未要求最小化步数,而且此题的操作可以进行倒退,于是我们可以构造一个简单的中间状态 —— \(1\) 全在 \((1,1)\),\(0\) 全在 \((2,1)\). 构造方式是先依靠列将 \(1/0\) 移动到指定行,再依靠行移动到指定点。
路径和优先考虑转化成深度(不妨设根的深度为零):
现在需要最小化后面一坨柿子,事实上它是可以取到零的。不妨设入点代表 \(p_i\),出点代表 \(i\),这就转换成一个匹配问题 —— 能否将所有出/入点配对使得其 \(\rm lca\) 均为根节点?考虑证明,令子树 \(u\) 的出点个数为 \(\text{out}_u\),入点个数同理。那么考虑每棵子树(这里及之后的子树特指根的儿子统领的子树),必须在每时每刻都满足 \(\text{in}_u\le \sum \text{out}_i-\text{out}_u\) 也即 \(\text{in}_u+\text{out}_u\le \sum \text{out}_i=\sum \text{in}_i\). 之后我们将根也看作一棵大小为 \(1\) 的子树。
考虑初始状态有 \(\text{in}_u=\text{out}_u=\text{siz}_u,\sum \text{in}_i=n\),所以每棵子树需要满足 \(2\cdot \text{siz}_u\le n\),这不就是重心的定义吗?于是选取重心为根。
我们先阐述构造方式,最后给出严谨性的证明。由于要求字典序最小,所以从出点 \(1\) 开始往出点 \(n\) 匹配,每次尽量选择最小的点。假设匹配到第 \(i\) 个出点,那么 \(\sum \text{out}_i=n-i+1\).
- 若存在 \(u\) 使得 \(\text{in}_u+\text{out}_u= \sum \text{out}_i\):此时必须保证 \(i,p_i\) 中 有且只有 一个点在子树 \(u\). 所以若 \(i\) 不在子树 \(u\) 中,就必须选择子树 \(u\) 中最小的入点。需要注意的是,若 \(u\) 为根节点不用管这条限制。
- 若不存在 \(u\) 使得 \(\text{in}_u+\text{out}_u= \sum \text{out}_i\),或者存在 \(u\) 使得 \(\text{in}_u+\text{out}_u= \sum \text{out}_i\) 但 \(i\) 在子树 \(u\) 中:选择当前最小且与 \(i\) 不在同一子树的入点即可。
具体可以用 \(3\) 个 \(\rm set\) 实现:一个维护最小入点,一个维护 \(\text{in}_u+\text{out}_u\),最后一个维护子树最小入点。
你可能会有一个疑惑,难道不会出现满足 \(\text{in}_u+\text{out}_u= \sum \text{out}_i\) 的子树有很多个,导致构造方式无法构造出合法解的情况吗?
事实上,可以证明至多有两棵子树满足以上条件,且其余子树均被匹配完,不妨设这两棵子树为 \(a,b\),那么有:
那么
接着有
所以有
即
同理也可以证得
于是除开 \(a,b\) 两棵子树,其它子树均被匹配完。这也就意味着,此时我们只能分别匹配 \(a,b\) 两个子树的点,那么它们将保持 \(\text{in}_a+\text{out}_a=\text{in}_b+\text{out}_b= \sum \text{out}_i= \sum \text{in}_i\) 的状态一直到结束匹配!所以我们的构造一定合法。
例 3. \(\text{CF1329B Dreamoon Likes Sequences}\)
假设 \(a_i\) 的二进制位数为 \(c_i\),一个结论是 \(c_i\) 严格递增。证明可以用数学归纳法:首先由 \(a_{i}>a_{i-1}\) 得 \(c_i\ge c_{i-1}\). 进行到 \(i=2\) 时,\(b_1\) 的最高位一定是 \(c_1\),所以若 \(c_i=c_{i-1}\),那么 \(b_2\) 最高位小于 \(c_1\),得出 \(b_2<b_1\)……归纳可得 "\(b_i\) 的最高位一定是 \(c_i\)" 的结论,那么上文的结论也就容易证明了。
由于是任意长度,我们可以直接算出每一种位数 \(a\) 的方案数,再将每一种位数相乘得到答案(第 \(i\) 位系数为 \(2^i+1\),即有和没有),最后不要忘记 \(n=0\) 的情况。
例 4. \(\text{P6196 }\)代价
首先一个结论是 "\(1\) 必须最后取",可以这样感性的思考:一定找不到比 \(1\) 更好的邻居了,所以删去 \(1\) 也无法找到更好的邻居。那么对于两端为 \(1\) 的非 \(1\) 段,从两端开始取,这个也可以进行感性的思考:整段的乘积个数是一定的,如果从两端开始取,意味着每个数字至多对两个乘积进行贡献。而对于其它的方案都无法保证这一性质。
例 5. \(\text{exchange your brains!}\)
例 6. \(\text{[AGC015D] A or...or B Problem}\)
先提一嘴,在翻这题的题解时看到了 \(\text{or,xor,and}\) 的一些转化,先放在这里:
第一次看这道题可能会很乱,事实上可以先从 \(\rm or\) 运算的简单性质入手:只能变得更大。所以最后或出来的最小值一定为 \(l\). 由于 \([l,r]\) 已经获得,所以目标转化成 "拓展 \(r\)"。
自然地,我们选取 \(l\) 与 \(r\) 第一个不相同的二进制位 \(\rm pos\)(之前相同的二进制位在最后的答案中是一定不可避免的,令其为 \(\rm base\)),令 \(z=\text{base}+2^{\rm pos}\). 考虑 \([l,z)\),显然与 \(z\) 或起来最大的区间是 \([z\mid l,z\mid (z-1)]\),并且 \(z\mid (z-1)\) 也是我们能够得到的最大数字;但是,\((r,z\mid l)\) 之间能不能新增新的数字呢?我们现在利用 \(z\) 与 \((z,r]\) 之间的数字或起来:找到比 \(\rm pos\) 小的第一个 \(r\) 为 \(1\) 的二进制位 \(j\),显然总存在 \(\text{base}+2^k\ \ (k\in[0,j])\) 这一系列数,用这些数可以组合出 \([\text{base},\text{base}+2^{j+1})\) 之间的所有数字,或上 \(z\),就能组合出 \([\text{base}+2^{\rm pos},\text{base}+2^{j+1}+2^{\rm pos})\) 的所有数字。这也是区间 \((z,r]\) 能贡献的极限了。
初始一定有 \([l,z)\),再将 \([\text{base}+2^{\rm pos},\text{base}+2^{j+1}+2^{\rm pos})\) 与 \([z\mid l,z\mid (z-1)]\) 求并即可。
最后,可以自己想想为啥不将 \([l,z)\) 与 \((z,r]\) 之间的数字或起来。
浙公网安备 33010602011771号