10月杂题
P9527 [JOISC2022] 洒水器
很妙的题。
显然要对祖先打标记。
如何打,\(d\) 很小,可以暴力跳,同时启发我们设 \(f_{x,d}\) 表示 \(x\) 子树内与 \(x\) 距离为 \(d\) 的标记,查询时直接暴力跳 \(40\) 个祖先即可。
但是直接打标记会重复,被修改节点所在的那一条链会被修改多次。一顿分析发现其实就是在 \(f_{p,d-dis(p,x)}\) 和 \(f_{p,d-dis(p,x)-1}\) 处打标记。
反思:数据范围不仅可以对时间优化有启发,还可以压进空间里。
CF1295F Good Contest
显然要离散化,将 \([a_i,b_i]\) 变成左闭右开的形式。
设 \(f_{i,j}\) 表示第 \(i\) 个数在第 \(j\) 个区间的方案数。枚举同在一个区间的连续段起点 \(k+1\),然后从 \(f_k\) 转移过来。
P3665 [USACO17OPEN] Switch Grass P
发现最短路径一定是一条边,于是有一种枚举所有出边的做法,会被菊花图卡。
还有一个结论,这条边一定在最小生成树上。
是树就好办了,对每个父亲开一棵线段树,下标为颜色,然后维护每个孩子中的最小距离。
修改只会影响自己和父亲的答案,只会修改父亲的线段树。在叶子处用 multiset 维护该种颜色所有距离,然后往上合并。
反思:对题目挖掘性质不要停留在粗浅的层面,需深度挖掘有利的性质。
P9520 [JOISC2022] 监狱
猜测:无解当且仅当某两条线段互相夹住另一条线段的一个端点,或者一条线段完全包含另一条线段。
但是结论假掉了……(第二个样例)。
判断非法比较困难,考虑如何判断合法。
如果合法,则存在一种先后顺序使得他们可以顺利到达。观察得到可以若合法则存在一种方式使得每个人都不停顿地走到终点,因此我们只需思考先后顺序。
有两条性质:
- 如果 \(A\) 的起点在 \(B\) 的路径上,那么 \(A\) 必须先于 \(B\) 走。
- 如果 \(A\) 的终点在 \(B\) 的路径上,那么 \(B\) 必须先于 \(A\) 走。
于是我们 得到一种 \(\mathcal{O}(n^2)\) 做法,暴力建边,然后拓扑排序判环。
优化就是树剖之后线段树优化建图。
P9017 [USACO23JAN] Lights Off G
显然要预处理。
Keys:初始开关的影响和变换开关的影响可以单独计算,所以我们可以预处理某个状态能否在 \(i\) 步内完成。
操作上界为 \(3n\)。把循环同构的拿出来可以优化到 \(\mathcal{O}(n2^n)\)。
反思:将初始和变化后的分开考虑。对于要预处理的题目,肯定得预处理初始状态一样的,这时将他们分开就很重要。
P9018 [USACO23JAN] Moo Route G
这种思维题是我不配做出来的。
首先要观察到,\(a_i\) 全是偶数,因为最后要回到 \(x=0\)(当然我没看见)。于是我们直接将 \(a_i\) 除以 \(2\)。
先从 \(n=2\) 开始入手,若 \(a_1>a_2\),显然就是有 \(a_2\) 次是 \(0\to 2\to 0\),还有 \(a_1-a_2\) 次是 \(0\to 1\to 0\),所以方案数就是 \(\dbinom{a_1}{a_2}\)。
若 \(a_1<a_2\),稍微麻烦一点,因为此时你走到 \(2\) 后可以选择回到 \(0\) 也可以不回。方案数是插板法 \(\dbinom{a_2-1}{a_1-1}\) 。
猜测这个可以推广到任意情况,于是就通过了。
反思:对题目的观察还是不够,从简单问题分析拓展到复杂情况的能力欠缺。
P1641 [SCOI2010] 生成字符串
反思:打表技术不够熟练,无限接近正解。
可以转化成从 \((0,0)\to (n,m)\) 且不穿过直线 \(y=x\) 的方案数。
若 \(n=m\) 那就是卡特兰数 \(\dfrac{\binom{n+m}{n}}{n+1}\),打个表发现不合法的方案数占 \(\dfrac{m}{n+1}\),所以总方案数就是 \(\dfrac{n+1-m}{n+1}\dbinom{n+m}{m}\) 。
另一种理解方式是用折线图,当接触 \(y=-1\) 时翻折一下,就可以发现不合法方案数是 \(\binom{n+m}{n+1}\)。都是类似卡特兰数的分析。
P9019 [USACO23JAN] Tractor Paths P
第一问可以倍增轻松求出。
如何做第二问,一直想着枚举关键点,但这样肯定做不了。既然我们都倍增了,那我们枚举什么时候脱离原有路径的步数 \(i\),则答案为 \(\sum\limits_{i=1}^{ans-1}cnt(g_{b,ans-i},f_{a,i})\)。拆成前后缀之后倍增维护即可。时间复杂度 \(\mathcal{O}(n\log n)\)。
反思:思考时应从已知、已求出、前面用过的信息入手。
[ARC180B] Improve Inversions
猜!
猜测答案是长度大于等于 \(k\) 的逆序对个数。
找出所有能换的位置,先换数值小的,再换大的。
怎么换,对于一个 \(P_i\),找到能换的候选项集合 \(\{s_1,\dots,s_m\}\),然后先换大的再换小的。最后应该是 \(s_1\) 在 \(P_i\) 的位置上。
好的我对了。
[ARC180C] Subsequence and Prefix Sum
发现 \(0\) 有很大的影响。发现第一个选的数也有很大影响(但这种可以归类为前面那种,因为初始值为 \(0\))。
一旦前缀和出现了 \(0\),后面如果只选一个数,那么跟不选没区别。如果选不止一个数,那么第一个数要是相同的选哪个都一样。怎么办?
一开始想用最小表示法,但不会 。
发现自己智力不够,思维混乱,我们只需再记录 \(g_i\) 表示前面和为 \(i\) 且上一次为 \(0\) 的方案数。然后我们不用 \(f_{i-1,0}\) 转移到 \(f_{i,a_i}\),这样就避免了选一个数的情况。然后用 \(g_j\to f_{i,j+a_i}\),就计算上了不止选一个数的情况。每次循环后,\(g_{a_i}\leftarrow g_0\),\(g_0\leftarrow f_{i,0}\)。
反思:思维混乱,在计数题中是大忌。要学会归纳各种情况,减少复杂的分类讨论,规约为简单的问题。
P9189 [USACO23OPEN] Custodial Cleanup G
猜测是先把所有钥匙收集,再按一定顺序放置。
第一问可以用搜索解决。
注意到一些结论:与 \(1\) 相连的点必须满足 \(c_i=f_i\)。
猜测:把所有满足 \(f_i=c_i\) 的点和 \(1\) 号点的 \(c_i\) 压入桶里。如果桶里的颜色能够进入任何一个不满足 \(c_i=f_i\) 的点,那就可以。
好像不对。
看了题解感觉很sb。
发现第二问一种合法的方案,倒过来其实就是以 \(1\) 为起点的拿钥匙方案,只是从拿 \(s\) 变成了拿 \(f\)。
于是也可以用类似方法解决。
P9192 [USACO23OPEN] Pareidolia P
稍微猜测是子序列自动机上动态 DP。
因为要求所有子串,设 \(sum\) 表示前一位匹配的方案数总和,考虑从 \(i-1\to i\):
- \(f_{i,j}=\max(f_{i-1,j-1}[s_i=t_j],f_{i-1,j})\)
- \(sum'= sum+f_{i-1,5}\)
- \(ans'=ans+sum'\)
线段树维护矩阵即可。
CF280C Game on Tree
发现树形 DP 是困难的。
设 \(f_i\) 表示 \(i\) 点被选中的次数,显然 \(f_i=0/1\)。为什么这样设??因为和题目要求有关,也有人称此为指示器随机变量。
要求的就是 \(E(\sum f_i)=\sum E(f_i)\),而 \(E(f_i)=P_i\),即 \(i\) 点被选中的概率,如何求???
显然一定要比它的祖先先选,所以概率是 \(\dfrac{1}{dep_i}\)。
P9131 [USACO23FEB] Problem Setting P
先考虑状压出每道题的状态,状态相同的单独考虑。然后思考转化判定条件:其实就是满足前一道题是后一题的子集。
那我们设 \(f_s\) 表示最后一道是 \(s\) 状态的题,枚举子集直接转移,时间复杂度 \(\mathcal{O}(3^m)\)。
一个 Trick:将状压后的数折半,分成前后两部分。
设 \(s_{i,j}\) 表示满足 \(x\) 前 \(10\) 位是 \(i\),后 \(10\) 位是 \(j\) 子集的 \(f_x\) 的总和。那么转移的时候只需枚举前 \(10\) 位,修改 \(s\) 时只需枚举后 \(10\) 位。可以做到 \(\mathcal{O}(n2^{m/2})\)。
有一个大神 DP:考虑优化枚举子集,考虑每次加入一个元素,按 \(|S|\) 转移,从集合 \(i\to i\cup \{s_1,s_2,\dots,s_k\}\) 有 \(k!\) 种方式。
设 \(f_{i,j}\) 表示现在走到集合 \(i\),用了 \(j\) 步的方案。
- 下一步走到的集合不选:\(f_{i\cup \{x\},j+1}\leftarrow f_{i,j}\)
- 下一步走到的集合选:\(f_{i\cup\{x\},0}\leftarrow f_{i,j}\times \dfrac{1}{(j+1)!}\times val_{i\cup \{x\}}\)
反思:转化判定条件,配合一些 Trick 的使用。
P2467 [SDOI2010] 地精部落
一直想着插入 DP,后面发现好像处理不了边界?
还是考虑从小到大加数。发现答案要么是 M 字形,要么是 W 字形,我们只需算一种就好了。
设 \(f_{i,j}\) 表示以 \(j\) 结尾的排列 \(1\sim i\),考虑转移。
枚举上一次的结尾 \(k\),可以看作将 \(f_{i-1,k}\) 里 \(\ge j\) 的数全部加一。于是就可以直接做。
反思:不要先入为主,陷入思维困境,及时从死胡同里跳出来。不过原方法的有些部分可以借鉴,比如这题可借鉴从排列的角度入手。
P9020 [USACO23JAN] Mana Collection P
很不错的题。
首先还是得分析性质,发现可以在每个点一直等到某个时刻,然后再一次性跑到终点。
而且我们可以只在经过每个点的最后一次记录。
考虑正难则反,算一条路径的最小损失量,设其为 \(f\),则答案为 \(\sum\limits_{i\in \operatorname{path}} m_i\times t-f\)。这个是关于 \(t\) 的一次函数,可以李超线段树维护。
设 \(f_{s,i}\) 表示集合为 \(s\),最后在 \(i\) 的最小损失量。这个可以费用提前计算:\(f_{s,i}\times sum_s\times dis_{i,j}\to f_{s\cup \{j\},j}\)。其中 \(dis_{i,j}\) 可以 floyd 直接求出。
有一个问题是可能会插入长度大于 \(t\) 的路径,但这不影响,因为大于 \(t\) 的那一段一定是负贡献。
反思:正难则反,挖掘出性质后设计合理的算法解决问题。
P5336 [THUSC2016] 成绩单
设 \(f_{l,r}\) 表示把 \([l,r]\) 全部取完的代价,然后我们发现转移有点抽象,因为一个区间可能会被拆成很多个离散的段。因为数据范围小,我们尝试将状态扩展一下,设 \(g_{l,r,mn,mx}\) 表示区间 \([l,r]\) 还剩下的数中最小值最大值分别是 \(mn,mx\) 的最小代价,那么有转移:
考虑 \(g_{l,r,mn,mx}\) 的转移,枚举断点 \(k\),那么 \([l,k]\) 和 \([k+1,r]\) 这两段要么都剩下值域 \(\in[mn,mx]\) 的,要么有一段全部取完,那么转移可以写出来了。
离散化后时间复杂度 \(\mathcal{O}(n^5)\)。
反思:难以维护的东西就写进状态。
[ARC185D] Random Walk on Tree
一开始从 \(n=1\) 开始考虑,发现这不太好,应该从 \(m=1\) 考虑。
将 \(0\to i\to 0\) 设为一次往返,设 \(f_i\) 表示已经涂了 \(i\) 个点,到涂完 \(n\) 个点的期望往返次数,则 \(f_i=\dfrac{n}{n-i}+f_{i+1}\)。
答案即为 \(f_0\times 2-1\)。
现在考虑 \(m\ne 1\) 的情况。如何计算期望往返次数,可以看作 \(0\to (m-1)n+i\to 0\),将 \(0\to (m-1)n+i\) 的期望次数乘 \(2\)。关于这个的计算,可以使用 CF1823F 的做法。当然也有结论:往返次数为 \(2m^2\)。
所以答案就是 \(m=1\) 的答案乘上 \(m^2\)。
反思:从特殊到一般的过程中,特殊情况可以多样化考虑,不能局限于一种。
P2685 [TJOI2012] 桥
删边最短路模板题。
在最短路树上考虑,记 \(T_1,T_n\) 分别表示从 \(1\) 出发和到达 \(n\) 的最短路树。在 \(T_n\) 上找到一条 \(1\rightsquigarrow n\) 的最短路 \(P\)。
- 若 \(e\not\in P\),则最短路不变。
- 否则,枚举边 \((u,v)\),若 \(T_1(1\rightsquigarrow u),T_n(v\rightsquigarrow n)\) 都不包含边 \(e\),则 可以用 \(edge(T_1(1\rightsquigarrow u))+edge(u,v)+egde(T_n(v\rightsquigarrow n))\) 来更新 \(e\) 的删边最短路。
但这样复杂度仍然不对。我们发现一条边 \((u,v)\) 可能可以对很多个 \(e\) 产生贡献。找到 \(T_1(1\rightsquigarrow u)\) 和 \(T_1(1\rightsquigarrow n)\) 的分界点,记为 \(L_u\),同理也有 \(R_u\)。那么一条边 \((u,v)\) 就有可能对 \(P\) 上面 \([L_u,R_v)\) 这个区间的边产生贡献,拿个线段树维护一下 \(P\) 的删边最短路就好了。
时间复杂度 \(\mathcal{O}(n\log n)\)。
P11189 「KDOI-10」水杯降温
真难吧。
考虑先做操作二再做操作一。这两个操作都有很浓烈的对「差分」的暗示,于是我们设每个点的差分值表示自己减去父亲。这样操作一相当于单点加一。
可以只用操作一完成的局面当且仅当所有节点的差分值小于等于 \(0\),且根节点的点权小于等于 \(0\)。而两个操作都无法使根节点以外的点差分值减少。所以若初始存在非根节点差分值大于 \(0\) 则无解。
现在就是要保证每个点差分值合法的情况下要求根节点点权最小。设 \(f_u\) 表示 \(u\) 子树在满足上述条件下最多能做几次操作二。考虑从 \(f_v\) 推到 \(f_u\)。
发现每次操作二都会使除了 \(v\) 以外的其它 \(u\) 儿子的差分值 \(+1\),于是设 \(d_v=a_u-a_v\),我们转化为下面的问题:
\(n\) 堆石子,每堆有 \(d_i\) 个,每次从 \(n-1\) 堆里取一个,每堆最多 \(f_i\) 次不取,问最多取多少次。
可以看作是先全取再用找一堆放回去。二分答案 \(x\),需要满足 \(\sum \max(0,x-d_i)\le x\),\(x-d_i\le f_i\)。
最后只需判断 \(a_1-f_1\) 是否小于等于 \(0\) 即可。
反思:对这种涉及一些抽象操作的一定要尝试简化操作,这不仅依赖于套路经验之谈,也跟做题直觉有关系。比如这题带有差分意向的暗示,就是解题的关键。
P11190 「KDOI-10」反回文串
比较好想的构造题,主要是特殊性质提示的很明显。
小于等于 \(n/2\) 的可以直接两两匹配。
否则,记 \(ta\) 表示出现次数最多的字母出现次数,\(tb=n-ta\),那么我们就要让 \(ta-tb+1\) 个出现次数最多的字母和一个剩下的字母匹配。
上述操作若都能匹配,剩下的要么是奇数,要么是偶数。对于奇数的就先拿出三个,剩下的再两两匹配就好了。
P9984 [USACO23DEC] A Graph Problem P
注意到给定过程其实是 Prim 算法。
但 Prim 算法我们不熟悉,于是我们从 Kruskal 算法考虑。建出重构树,我们发现一条连接了 \(u,v\) 两个联通块的边 \(e\),\(u\) 联通块的答案更新为原答案加上 \(e\) 再加上 \(v\) 里的原答案。\(v\) 答案的更新同理。
线段树已经足以解决。但是有更简单的做法,就是带权并查集。tag 合并顺序从底向上,支持路径压缩。
P9130 [USACO23FEB] Hungry Cow P
感觉像是分治。
考虑动态开点线段树维护每一天的干草。
问题是这个东西怎么算答案??每个区间可以往右边区间贡献一些东西,使得答案的计算没有那么容易。
考虑楼房重建线段树,通过递归右儿子的方式来计算答案。
对于每个区间,我们维护区间答案 \(ans\),区间有草吃的天数 \(num\),区间对右边区间的贡献 \(s\),左儿子对右儿子的贡献 \(son\)。
\(son\) 的求解,需要递归右儿子。设 \(\operatorname{query}(l,r,x)\) 表示当左边区间对自己有 \(x\) 时,区间的答案。分递归左儿子和右儿子讨论一下就好了。
反思:线段树太好用了,学习 DS 的处理技巧。
P8907 [USACO22DEC] Making Friends P
可以感觉到是启发式合并,但是不知道怎么合并。
观察到若我们删除一个点之后暴力将与它相连的所有点两两之间连边,那之后可能还存在删点的情况,这是不优的。而因为删除顺序是 \(1\sim n\),于是我们直接钦定从编号最小的点连向其余点就好了。
反思:对缩减边数规模降低复杂度的运用不够熟练。思考优化的时候可以从「如果暴力会带来怎样的不良影响」 的角度思考。
P8276 [USACO22OPEN] Hoof and Brain
太神了。
首先发现若存在一个点无出边,则 B 赢。这可以通过对反图拓扑排序实现。然后呢??
将原图中出度为 \(0\) 的点去掉,建出新图 。然后做一个大神染色:
- 初始时每个点 \(col_i=i\)。
- 若存在点 \(i\) 使得它出去的所有点颜色都相同,那么令所有颜色为 \(col_i\) 的点都变成该颜色
- 重复上述步骤直到无法操作。
这时我们发现,若 \(col_x=col_y\) 则 B 赢,否则 H 赢!!!
为什么?因为一个 \(u\) 点必然会走到 \(col_u\) 这个点,所以若 \(col_x=col_y\) 则 \(x,y\) 会在 \(col_x\) 这个点上堵死。
如何维护 \(col\) ?维护每个点出去的点的颜色种类集合,然后启发式合并。
反思:大神染色法。
[ARC181D] Prefix Bubble Sort
发现要是在某一次排序过程中 \(x\) 被换到了 \(y\) 位置。那么在此之后 \(y\) 都不会再发生改变了,因为前面没有比它更大的数,而后面的数也不可能换到前面。
使用链表维护即可???有点难写这东西。
其实我们可以换个角度,从被换到前面的那些数字入手。这些数每被往前滑动一次,逆序对就减少 \(1\)。而哪些数会被往前换呢??其实就是非前缀最大值的位置。于是我们可以计算每一个位置的贡献,然后就做完了。
反思:思维还是不够灵活,容易陷入死胡同走不出来,不肯换角度思考。
P8099 [USACO22JAN] Minimizing Haybales P
对于每个位置,在值域上二分出最小的能够换到这里的数,然后换到这里,这个东西要维护一个区间最大值、最小值。
这tm是错的,这东西没有单调性。
不如考虑每个数往前换,这样就好多了。
反思:一如既往的在子胡同里乱转。
CF1632D New Year Concert
设 \(ans_i\) 表示长度为 \(i\) 的 \(a\) 前缀答案。
首先有 \(ans_i=ans_{i-1}\),然后只需考虑是否删掉这个 \(i\)。
有经典结论:固定右端点 \(r\) 的时候,它的后缀 \(\gcd\) 最多只有 \(\log V\) 种。
于是我们可以求出所有以 \(i\) 结尾的后缀 \(\gcd\),然后判断一下这个 \(\gcd\) 是否可能会等于一个后缀长度即可。如果存在这样的 \(\gcd\),就把 \(a_i\) 改为一个大质数,然后 \(ans_i\) 加一。
时间复杂度 \(\mathcal{O}(n\log V)\)。
P8100 [USACO22JAN] Counting Haybales P
首先要注意到差值 \(>1\) 的两个元素不能改变相对位置,钦定相同元素的也不能交换。这样就可以变成一个 DAG 拓扑序计数。
但是一般的 DAG 拓扑序计数是不能做的,继续挖掘性质,发现奇数的拓扑序是唯一的,偶数也是,这样只有两条拓扑序固定的链相互连边,这样就能做了。
反思:DAG 拓扑序计数感觉是一种可以应用在某些计数题的好方法。这些计数题的元素之间存在一些先后顺序的要求,这时就可以应用这种模型。当然如何挖掘「差值为 \(1\)」这个条件,它启发我们思考这个东西是否能够限制一些元素的相对顺序,挖掘出这个条件后我们就可以使用上述模型。当然还要继续挖掘性质,继续利用这个条件联想到奇偶性,很强!
CF2025E Card Game
首先题目的意思就是,同种花色内部比较,数值大的牌厉害。而花色 \(1\) 又可以击败其它任意花色。
我们发现除了 \(1\) 以外的不同花色间是不能比较的,所以在没有 \(1\) 号牌的情况下,先手能赢肯定是对于任意一种花色,先手后手都各自选择一半,设先手选了 \(a_1<a_2<\dots<a_{m/2}\),后手选了 \(b_1<b_2<\dots<b_{m/2}\),都有 \(a_i>b_i\)。将后手的选择看成 \(+1\),先手看成 \(-1\),则对于同种花色的任意一种合法选择方案,需要满足任意的前缀,前缀和 \(s_i\ge 0\),这可以用卡特兰数解决。具体的,可以看作是从 \((0,0)\) 走到 \((\frac{m}{2},\frac{m}{2})\) 且不穿过直线 \(y=x\),第一步必须向右走的方案数,为 \(\dfrac{\dbinom{m}{\frac{m}{2}}}{\frac{m}{2}+1}\)。
现在有了 \(1\) 号牌就没那么简单了,我们考虑枚举用去打其它花色的牌的个数 \(t\),剩下 \(m-t\) 张 \(1\) 号牌内部互相斗。那这时候其它牌就不一定要满足上述条件,设 \(dp_{i,j}\) 表示 \(2\sim i\) 这些花色,用了 \(j\) 张花色 \(1\) 的合法方案数。枚举花色 \(i+1\) 用几张 \(1\) 号牌,设为 \(k\),则 \(dp_{i,j}\times f(k)\to dp_{i+1,j+k}\)。其中 \(f(k)\) 表示在用 \(k\) 张一号牌的情况下,有多少种合法的分牌方式。
如何求 \(f(k)\)?首先仍然要满足任意前缀 \(s_i\ge 0\),但是现在先手只需要选出 \(\dfrac{m-k}{2}\) 张牌就好了,这可以看作从 \((0,0)\) 走到 \((m-\frac{m-k}{2},\frac{m-k}{2})\) ,且不穿过直线 \(y=x\),第一步必须向右走的方案数。设 \(X=m-\frac{m-k}{2},Y=\frac{m-k}{2}\),由 P1641 的理论,我们知道这个方案数是 \(\dfrac{X+1-Y}{X+1}\dbinom{X+Y}{X}\)。
现在只需要计算合法的花色 \(1\) 的分配方案,再乘上 \(dp_{n,t}\) 就好了。发现把合法的一种花色 \(1\) 选择方案倒过来(整个序列翻转之后,\(1\to -1\),\(-1\to 1\)),就是一种合法的其它花色选择方案,所以也是 \(f(t)\)。
最终答案就是 \(\sum \limits_{t\in \operatorname{even}} dp_{n,t}\times f(t)\)。
CF2025F Choose Your Queries
题解说这是经典问题。
考虑图论建模,将询问的两个点连无向边,现在要做的就是给每条边定向,并赋值。
我们发现,对于一组有公共点的边 \(e_1,e_2\),设公共点为 \(v\),那么我们可以让两条边都指向 \(v\),给编号小的赋值 \(+1\),编号大的赋值 \(-1\),这样可以保证任意时刻大于 \(0\) 并且操作影响抵消。
现在问题就变成了将无向图划分成最多的边对,使得每个对的两条边都有公共点。这是经典问题:
我们在图的 DFS 树上考虑,设当前在 \(u\) 点。每次将 \(u\) 到儿子的边以及回边两两配对。可能会剩下一条,这时我们用 \(u\) 到父亲的边与其配对。最后最多在根剩下一条边。
P11191 「KDOI-10」超级演出
设 \(L_i\) 表示让 \(a_i\) 出场的最大 \(l\),\(R_i\) 表示下一个满足 \(a_j=a_i\) 的 \(j\)。
对于一次询问,就是问区间 \([l,r]\) 内 \(L_i\ge l,R_i>r\) 的 \(i\) 个数。拆成差分的形式就是一个 CDQ 分治。
\(R_i\) 是容易求的,怎么求出 \(L_i\)?有一个朴素的转移 \(L_i=\max L_j\),其中满足存在 \(a_j\to a_i\) 的边。发现这个东西其实可以根号分治。对于前驱结点 \(\le \sqrt{m}\) 的,可以直接暴力枚举前驱结点。\(>\sqrt{m}\) 的,这样的点 \(\le \sqrt{m}\) 个,所以可以开一个数组维护这些点的答案。每次求出一个新的 \(L_i\),枚举这些点看能否更新。
但是多一个 \(R_i\) 很难受,我觉得还是得去掉。其实因为我们只关心最后一个,我们直接在枚举到 \(i\) 的之后把 \(las_{a_i}\) 的值在树状数组上去掉就好了。(PS:一直想带个 \(R_i\) 的原因是我一开始以为只能用主席树求那个玩意而主席树不带修……)
CF2030E MEXimize the Score
思考如何划分,显然分到一个集合内的数不能重复。
考虑往集合里加数,一开始所有集合的答案都是 \(0\)。现在加入了 \(t_0\) 个 \(0\),就有 \(t_0\) 个集合的答案加了 \(1\),再加入 \(t_1\) 个 \(1\),就有 \(\min(t_0,t_1)\) 个集合的答案加 \(1\)。可以发现,这个东西是一个前缀 \(\min\)。所以一个序列的答案就是 \(\sum\limits_{i=0}^{n-1} \min\{t_0\dots t_i\}\)。
设 \(f_{i,j}\) 表示 \(\min\{t_0\dots t_i\}=j\),考虑转移,若 \(i\) 这次要成为最小值,则 \(f_{i,j}=(\sum\limits_{k=j+1}^n f_{i-1,k})\dbinom{cnt_i}{j}\)。若 \(i\) 这次比最小值大,则 \(f_{i,j}=(\sum\limits_{k=j}^{cnt_i}\dbinom{cnt_i}{k})\times f_{i-1,j}\)。
最终答案是 \(f_{i,j}\times j\times \prod\limits_{k=i+1}^{n-1}2^k\)。
由于 \(\sum cnt_i=n\),时间复杂度 \(\mathcal{O}(n)\)。
CF2030F Orangutan Approved Subarrays
为啥没做出来呢??
显然线段相交就不行(包含可以),否则就可以。记 \(f_l\) 表示以 \(l\) 为左端点,右端点最远能到哪。如果能处理出这个东西就可以 \(\mathcal{O}(1)\) 回答。
对于区间 \([i,nxt_i]\) 来说,找出所有 \(j\in(i,nxt_i)\),\(nxt_j>nxt_i\) 的 \(j\),取 \(nxt_j\) 的最小值。然后再让 \(f_i\) 取一次后缀 \(\min\) 即可。将 \(nxt_i\) 从大到小排序即可使用线段树维护。
反思:不善于将转化后的模型套用经典的、通用的解法。就像这题,已经转化成了线段相交模型,但是还是没有去尝试跟排序有关的做法。当然直接分析也无问题,但是太唐了。
P9970 [THUPC 2024 初赛] 套娃
一类和 \(\operatorname{mex}\) 有关的问题。
定义满足 \(\operatorname{mex}(l,r)=x\) 的区间为 \(\operatorname{mex}_x\) 区间。对于一个 \(x-\operatorname{mex}\) 区间 \([l,r]\),如果不存在子区间也是 \(\operatorname{mex}_x\) 区间,则称 \([l,r]\) 为「极小的 \(\operatorname{mex}\) 区间」。
有结论:极小的 \(\operatorname{mex}\) 区间只有 \(\mathcal{O}(n)\) 个。
考虑一个极小的 \(\operatorname{mex}_x\) 区间 \([l,r]\),假设 \(a_l>a_r\),则删去 \(a_l\) 后,\(\operatorname{mex}\) 变为 \(a_l\)。不妨设 \([l+1,r]\) 对应的极小子区间为 \([L,R]\),因为 \(a_r\) 没有在 \((l,r)\) 中出现,而又在 \([L,R]\) 中出现 ,所以 \(R=r\)。
这说明:\(\operatorname{mex}_x\) 区间必定为一个 \(\operatorname{mex}_t\) 区间向一端扩展到第一个数 \(t\) 得到。其中 \(x>t\)。
考虑从 \(x=0\to n-1\) 依次求出 \(\operatorname{mex}_x\) 的极小区间,对于每个 \(x\) 维护 \(\operatorname{mex}_x\) 极小区间的 vector。时间复杂度是 \(\mathcal{O}(n\log n)\) 的。
接下来考虑所有对应 \(\operatorname{mex}_x\) 的极小子区间 \([l,r]\) 的大区间的形态。设 \(l\) 左边第一个 \(x\) 在 \(L-1\),右边第一个在 \(R+1\)。那么大区间的形态就是左端点在 \([L,l]\),右端点在 \([r,R]\) 之间的所有区间。于是 \(\forall len\in[r-l+1,R-L+1]\),存在长度为 \(len\) 的区间 \(\operatorname{mex}=x\)。
于是问题就变成了有 \(n\) 个集合,每次区间加数,最后对所有集合求 \(\operatorname{mex}\)。差分一下,拿个 set 维护一下就好了。
P10218 [省选联考 2024] 魔法手杖
首先考虑二分答案 \(mid\),需要判断是否存在 \(x\),使得:
- \(\forall i,a_i+x\ge mid\)
- \(\sum\limits_{a_i\oplus x<mid}b_i\le m\)
第一个条件容易满足,关键在第二个。
建出 Trie 树,枚举 \(x\) 这一位填什么,然后根据 \(mid\) 的大小判断一下,时间复杂度 \(\mathcal{O}(nk^2)\)。
对于位运算,逐位确定答案是比二分答案更优的。
考虑 \(ans\) 这一位是否能为 \(1\),若 \(x=0\),则左儿子要 \(+\),此时要求 \(\sum\limits_{i\in lc} b_i\le t\),\(t\) 表示剩余的体力,并且 \(\min\limits_{i\in lc} a_i +x\ge ans\),将 \(x\) 未确定的位都置为 \(1\),\(ans\) 未确定的位都置为 \(0\)(极端情况)。\(x=1\) 同理。
时间复杂度 \(\mathcal{O}(nk)\)。
P7831 [CCO2021] Travelling Merchant
考虑 DP,设 \(f_i\) 表示从 \(i\) 点出发的答案,则 \(f_u=\min\limits_{u\to v} \max(f_v-p,r)\)。
这样做的问题在于无法精确的给出一些点的初始值。
那么如何解决?我们需要继续挖掘图的性质,我们发现如果以 \(\max r_i\) 的资产出发一定能畅通无阻。而出度为 \(0\) 的点无解。
根据这个,我们可以从大到小考虑每一条边,然后综合拓扑排序与贪心设计一个算法,具体见 P7831。
反思:脑筋急转弯,多换角度思考。综合各种算法。
CF802L Send the Fool Further! (hard)
将这题和 CF1823F 混了。
那题求的是经过的期望次数,所以可以 \(f_u=\sum \dfrac{1}{\deg_v}f_v\)。
但是这题是求步数,显然得倒推,于是你得 \(f_u=\sum \dfrac{1}{\deg_u}(f_v+w(u,v))\)。
这样还是可以用套路去表出。
P5637 ckw的树
有点太难了吧。
想要用常用套路,但是因为涉及到距离 \(\le 2\) 的点,所以得变成
的形式。
最初的式子还含有儿子、儿子的儿子、兄弟三种。前面两种展开后都是简单的,关键在于后面一种。
在上面那个式子的基础上加上 \(D\sum \limits_{v\in bro(u)} f_v\)。可以用经典递推套路,将 \(u\) 表示成只跟它的后缀兄弟有关,然后再倒推回去。那么我们在 \(fa_u\) 处考虑它的所有儿子,就可以计算兄弟的贡献。
代码抄的卷哥。

浙公网安备 33010602011771号