2024.12.24 LGJ Round
实在是难以相信我竟然又来到了机房训练。
P10141 [USACO24JAN] Merging Cells P
一个简单的 \(dp_{i,l,r}\) 表示最后如果剩下的是 \(i\),当前 \(i\) 所处的区间是 \([l,r]\) 的概率。
区间往外拓展当前仅当当前 \([l,r]\) 区间的和不小于拓展的区间的和。
然而状态数已经达到 \(O(n^3)\),完全无法优化。
注意到初始条件是 \(dp_{i,i,i}=1\),而 dp 是一个路径计数过程,考虑将 DAG 图反置。
也就是原本我们是区间的合并,现在时光倒流,转化为区间的分割来划分子任务。
也就是求从 \([1,n]\) 开始,存在 \([l,r]\) 这样一个区间是被分割的。
考虑区间分割的点 \(p\in[l,r-1]\),是等概率选择的,然后哪边大就贡献到哪边的区间,另一边舍弃。
考虑前缀和优化,维护 \(sum_{l,i}\) 表示左端点为 \(l\),右端点为 \(i\) 时被贡献多少。固定右端点同。
P4437 [HNOI/AHOI2018] 排列
看式子的形式应该是贪心,我们即需要让后面的 \(w_{p_i}\) 尽量大,考虑从后往前填。
那么我们可以得到一个条件就是,要想填 \(a_j\),即 \(a_{p_i}=j\),那么 \(j\) 必须已经被填了。
这非常像一个图论建模。考虑 \(j\) 向 \(a_j\) 连一条边。那么如果不是 DAG 就无解。
如果是 DAG,进一步地其实这就是一棵内向树,考虑从根节点,也就是 \(0\) 号点开始删。
很典是吧,转化为选平均数最小的若干段。取出平均值最小的点 \(x\),然后将 \(x\) 与父亲合并。
合并代表的是,若 \(x\) 父亲被选了,那么下一个一定选的是 \(x\)。然后重复该过程,直到只有一个点。
关于答案的计算,只需要在每次合并的时候累加上 \(w_x\) 乘父亲的大小即可。考虑并查集维护。
这是一个形而上学的问题。
P4654 [CEOI2017] Mousetrap
考虑先给树定根,很显然要定到 \(t\) 这个点。
考虑整个过程是什么样的,老鼠显然最后一直走走到一个叶子节点。
当老鼠被困住的时候,我们可以先堵住不是前往 \(t\) 的所有边,然后再擦除每条去 \(t\) 的边。
而在老鼠走向叶子的过程中,我们可以堵塞其一些道路,我们要堵塞其花费最大代价的道路。
考虑树形 dp 设 \(f_u\) 表示一个子树内的答案,那么 \(f_u=deg_u-1+2nd\max f_v\)。
如果 \(s\) 与 \(t\) 之间只有一条边,那么答案就是 \(s\) 次大的子树代价加上 \(deg_s-1\)。
考虑可以从 \(s\) 往上走再岔进某个子树。这时候比较难算,考虑二分答案 \(v\)。
在往上走的时候,如果有子树的答案超过了当前的 \(v\),就要给他堵住,并使得 \(v\) 减去 \(1\)。
并且,需要堵住的个数不超过当前能用的步数。满足以上的条件 \(v\) 就是合法的。
ARC140D One to One
首先联通块的个数等同于环的个数。考虑拆贡献到每个环。
如果已经存在的环,我们直接加上其贡献。现在问题就是已知有若干棵内向树,要把他们拼成环。
设总共有 \(m\) 棵树,那么设一个大小为 \(k\) 棵树的环,那么其出现的次数就是 \(n^{m-k}\)。
对于钦定某 \(k\) 棵树构成的环,方案数是 \((k-1)!\prod siz_k\),代表每棵树的根连向哪里的贡献。
这是一个背包,简单解决即可。
AGC028C Min Cost Cycle
先贪心地选出 \(a,b\) 最小的 \(n\) 个数,那么我们选 \(n\) 条边,使得每条边都只有一个点被选。
经过手玩盲猜只需要存在一个 \(a_i,b_i\) 都被选就存在一种回路方案。
或者是 \(a\) 全都被选了或者 \(b\) 全都被选了。然后你后面瞎几把搞就行了。
ARC121D 1 or 2
逆天孩子,只需要把一个数看成与 \(0\) 匹配即可,然后枚举 \(0\) 的个数,最后贪心匹配。
P4426 [HNOI/AHOI2018] 毒瘤
新科技广义串并联图。
根据经典结论,通过以下三个操作,最终得到的图的边数是 \(V=2k,E=3k\) 级别的。
三个操作是:消串联(选一个二度点合并其两端);消并联(删重边),去断路(删一度点)。
考虑在上述过程中维护答案。考虑维护 \(f_u,g_u\) 表示考虑 \(u\) 上挂的点,\(u\) 选/不选的方案数。
同时维护每条边三种情况 \((0,0),(0,1),(1,0)\) 的方案数。
最后统计答案的话考虑枚举每个点选不选再乘起来即可。
消串联的话,考虑枚举中间的点是 \(0/1\),然后贡献简单计算。
消并联可以用一个 map 维护是否有边,注意到重边的贡献是独立,直接相乘即可。
去断路的话,就是更新与其连接的那个点的 \(f,g\) 值。
具体实现可以类比拓扑排序。
AGC005E Sugigma: The Showdown
观察样例,A 可以一直躲避下去的方式是已知躲在某条边,使得其两端点在 B 树的距离 \(\ge 3\)。
那么我们可以找出这样所有的边,只要 A 能到达这样的边那么 A 就获胜了。
所以 B 是要在 A 前往这些边的过程中阻碍 A 到达。
那么,所以如果 B 要获胜,那么一定不能让 A 到达这些边的任何一个端点对吧,
所以 B 到这些边的每个端点的距离一定是小于 A 所到达的,对吧。
如果 B 一定赢,那么 A 的策略一定是躲到距离 B 最远的某个叶子处,所以找到这个点即可。
是不是说 B 到上述每个对 A 胜利的点距离都比 A 小就赢了呢?是的,并且我们还可以在路上阻断他。
条件是如果 \(dis_{A,u}>=dis_{B,u}\) 那么 \(A\) 一定不能到达这个点 \(u\)。
可以理解为 B 就是走了一条最快靠近 A 的路,反正 A 是不能回头因为会更亏的。
所以我们以 A 定根做一遍 dfs,只能走 B 不能更快到达的点,看能不能走到一条胜利边即可。
如果走不到,就计算能走的点距离 B 最远的点是哪个,A 就躲在这里。
P7897 [Ynoi2006] spxmcq
对于每个 \(x\) 我们都有一个树形 dp 就是 \(dp_{u}=a_u+x+\sum \max(0,f_v)\)。
也就是:如果当前子树为贡献正数,那么就可以向父亲贡献。
同时因为这题可以离线,所以这启示我们按照 \(x\) 从小到大排序加入。
那么我们可以维护当前已经向上贡献的边,因为 \(x\) 从小到大,那么一旦贡献以后就都会有贡献。
所以我们相当于维护若干连通块。那么我们需要当 \(x\) 增加时寻找贡献将变为正数的子树。
设该子树目前总共有 \(siz\) 个点贡献,原始 \(a_i\) 的和距离 \(0\) 是 \(d\),\(x\) 增加到 \(d/siz\) (上取整)时即为正。
所以我们考虑用一个堆维护当前最小 \(d/siz\),每次取出最小的并向上合并,并更新上面的。
合并的话考虑用并查集处理。然后修改的话是一个链加的形式。差分转化为求子树和即可。
P8277 [USACO22OPEN] Up Down Subsequence P
贪心地,对于 \(i\) 结尾的子序列,一定是保留最长的最好。证明比较难,纯靠感觉。
那么树状数组维护 dp。
P10060 [SNOI2024] 树 V 图
考虑找充要条件,那么就是取出所有两端颜色不同的边出来,设这条边为 \((u,v)\)。
设 \(d_u\) 表示其到其对应的关键点的距离,钦定 \(f(u)<f(v)\),那么 \(d_u-d_v\in [0,1]\)。
同时注意到每个颜色形成一个连通块,连通块之间又有一个树形结构关系。
那么考虑树形 dp,设 \(f_{u,k}\) 表示 \(u\) 这个连通块,其关键点到顶端距离为 \(k\) 方案数。