集训总结(四)
9.9
P5522 棠梨煎雪
挑题的时候 qk 说这是线段树优化状压 dp,写完后看了看自己的代码,线段树?我怎么没有啊?状压 dp?我怎么没有啊?
考虑区间 \([l,r]\) 字符串每一位对答案造成的影响,设考虑到第 \(k\) 位:
1.第 \(k\) 位有 \(0\) 有 \(1\):此时无论 \(S\) 是什么,都不可能有贡献,答案为 \(0\)。
2.第 \(k\) 位有 \(0\) 或 \(1\):此时 \(S\) 的第 \(k\) 位也只能是 \(0\) 或 \(1\),答案不变。
3.第 \(k\) 位全为 \(?\):此时 \(S\) 的第 \(k\) 位 \(01\) 均可,根据乘法原理,答案 \(\times 2\)。
发现我们只需要维护区间某一位的 \(01\) 个数,于是我们对每一位的 \(0\) 和 \(1\) 个数都单独开一棵树状数组,由于 \(n\) 很小,所以我们可以直接暴力枚举,判断当前位 \(0\) 和 \(1\) 的个数即可。
复杂度 \(O(qnlogm)\) 但常数很小,没怎么卡就过了。
要永远相信树状数组的速度!!!
P7475 简易输入法
扫码了,卡我树套树空间。
对所有字符串建立字典树,跑一遍 \(dfs\),跑出 \(dfn\) 序,将树上问题转化为了序列问题,然后这就是一个裸的树套树板子了,直接上树状数组套权值线段树即可。
9.10
坏消息:模拟赛挂分了。
好消息:10元幸运奖抽到我了。
P2824 排序
发现直接排序有点难搞,考虑怎么转化。
发现我们只关心最终查询位置上的值,考虑对那个位置二分答案。设此时 \(check\) 的数是 \(k\),我们将所有大于等于 \(k\) 的数化为 \(1\),将所有小于 \(k\) 的数设为 \(0\),这样我们就将序列转化成了 \(01\) 序列。此时我们再看操作,相当于是找到区间 \(01\) 的分界点,然后区间推平,\(ODT\)/线段树维护一下就好了。
9.11
P13925 联合猫国
考虑 dp,枚举左端点 \(j\) 和右端点 \(i\),如果 \(i\) 到 \(j\) 可以合并就 \(dp_j+1 \to dp_i\)。
考虑固定 \(i\) 时如何快速枚举 \(j\)。注意到假设相邻两个合法的 \(j\) 分别为 \(k'\),\(k\),那么必有从 \(k'\) 到 \(k−1\) 合法且这一段合并的结果与 \(k\) 到 \(i\) 相等。
于是用一种类似倍增的方法,记录可以从哪里过来。容易发现这样复杂度是对的。最劣的情况大概是全相等的时候,转移次数 \(O(nlogn)\)。
P2774 方格取数问题
题目的限制条件相当于选了一个数,四周的数就不能选。将每个点拆成入点和出点,初始从点 \(s\) 向入点连 \(a_{i,j}\) 的边,从出点向 \(t\) 连 \(a_{i,j}\) 的边。对于每个点,四周的点不能选,就从这个点的入点向四周的出点连一条 \(inf\) 的边,之后跑最小割就可以了。
P2764 最小路径覆盖问题
最小路径覆盖=总点数-最大匹配。
跑匈牙利,记录一下每个点的前驱就可以了。