2024.8 做题记录
1.有依赖的背包问题
普及组题现在还不会。。。太有实力辣。
2.P6326 Shopping
题目的要求实质上是要我们选的位置构成一个连通块。
可以暴力枚举根做树上依赖背包。
优化的方法是点分治,计算经过当前重心的连通块,不经过的可以地柜计算。
时间复杂度 O(nmlogn)O(nmlogn)。
3.P3780 SDOI2017 苹果树
首先这个 t−h≤kt−h≤k 可以转化为“免费选一条根链,求至多选 kk 个的最大价值”。
考虑枚举这条根链,然后整棵树就被这条链划分成了两部分,且两部分是在 dfs 序上连续的,链上的部分可以选 ai−1ai−1 个,其余部分可以选 aiai 个。
不放将链上的部分合并到左边的部分,这样就可以预处理两部分的背包,然后 O(k)O(k) 查询答案。
具体来说,在 dfs 的时候,可以先放入 ai−1ai−1 个,然后递归儿子,合并儿子的时候再把儿子中少选的一个加上,这样算的就是对的。
时间复杂度 O(nk)O(nk)。
4.P3571 POI2014 SUP-Supercomputer
先将操作转化为每次最多删 kk 个叶子。
不难发现当叶子个数 ≤k≤k 的时候答案就是树高 hh。
当叶子数大于 kk 的时候,我们贪心地选深度最大的叶子删掉。
如果记 cnthcnth 表示深度大于 hh 的点数,那么答案可以表示为 maxh{h+⌈cnthk⌉}maxh{h+⌈cnthk⌉},证明可以看题解。
推一下式子:
里面这个是若干个一次函数的最大值,考虑类似斜率优化的方式推式子:
这就是说:有一些点 (−cnth,h)(−cnth,h),你要用斜率为 1k1k 的直线去切它,要截距最大。
维护上凸壳,斜率是单调的,所以扫一遍就行。
时间复杂度 O(n)O(n)。
5.P4383 八省联考 2018 林克卡特树
题意可转化为:选出恰好 kk 条链,使得权值和最大。
首先我们有暴力 DP:设 fu,i,0/1/2fu,i,0/1/2 表示以点 uu 为根的子树中选恰好 ii 条链,点 uu 的度数为 0 / 1 / 2 的最大权值。
转移就是分类讨论一下 (u,v)(u,v) 这条边选不选,做一个树上背包,较为繁琐。
时间复杂度 O(nk)O(nk)。
感觉一下没有什么阳间的优化方式,而且看到到“恰好”,考虑凸优化。
如果设 f(k)f(k) 表示选择恰好 kk 条边的最大权值,通过打表等方式可以发现它是凸的(具体证明见 https://www.luogu.com.cn/article/hkdxyitj)。
于是套个 WQS 二分就做完了。
时间复杂度 O(nlogn)O(nlogn)。
6.P5298 PKUWC2018 Minimax
设 fu,ifu,i 表示点 uu 权值为第 ii 大的数的概率,转移为:
然后线段树合并即可。
时间复杂度 O(nlogn)O(nlogn)。
7.Minecraft
设 fi,jfi,j 表示考虑完了从低往高的第 ii 位,进位为 jj 是否可行。
转移是平凡的。
输出方案的话同时记录一下转移即可。
时间复杂度 O(nk)O(nk)。
8.P4590 TJOI2018 游园会
首先考虑计算 LCS,这个可以通过 DP 简单实现。
考虑 DP 套 DP,先把内层的 DP 变成自动机。
考虑如何压缩节点数,不难发现 DP 数组单调不减且差分数组只有 0 和 1,所以可以只存差分数组。
剩下的 DP 就是简单的了,设 fi,j,0/1/2fi,j,0/1/2 表示确定了 ii 个字符,匹配了 0 / 1 / 2 个字符的方案数。
转移是简单的。时间复杂度 O(nk2k)O(nk2k)。
9.P5279 ZJOI2019 麻将
首先考虑如何判定一些牌是不是胡的:设 dpi,j,k0/1dpi,j,k0/1 表示考虑了前 ii 中牌,预留了形如 (i−1,i,i+1)(i−1,i,i+1) 的 jj 个,预留了形如 (i,i+1,i+2)(i,i+1,i+2) 的 kk 个,是否预留对子的方案数。
转移已是简单的,对于划分成 7 个对子的形式可以记一个 cntcnt 表示能取出的对子的数量然后简单判断。
先对原问题进行一个简单的转换:对于每种方案算胡的轮数之和 等于 算第 ii 轮还没胡的方案数之和。
考虑把上面的 DP 变成自动机然后在自动机上 DP。
先压缩状态:首先有 j,k≤2j,k≤2,因为如果等于 3 就可以直接凑成 3 个刻子,然后我们钦定 DP 值是 ≤4≤4 的。
这样状态就变成了 2091 个。
再考虑 DP:设 fi,j,kfi,j,k 表示考虑了前 ii 种牌,摸了 jj 张,在自动机上状态为 kk 的方案数。
转移是简单的。
时间复杂度 O(n2S)O(n2S),其中 S=2091S=2091。
10.P8497 NOI2022 移除石子
先考虑判定:设 dpi,j,kdpi,j,k 表示考虑了前 ii 个位置的石子,至少扩展到 ii 的操作 2 有 jj 个,至少扩展到 i+1i+1 的 ii 操作有 kk 个的是否可行,转移就是考虑 ii 位置开始了多少个操作 2。
要求计数,考虑将判定的 DP 变成自动机后在自动机上 DP。
先压状态数,不难通过看题解发现 j,k≤2j,k≤2,这样状态数就是 87658765 的了。
通过讨论可以发现,除了 “k=1k=1 且 ai=0ai=0” 和 “k=1,n=3,a1=a2=a3=1k=1,n=3,a1=a2=a3=1” 的情况,若 k−1k−1 有解, kk 一定有解。
所以上面的 DP 可以将 “是否可行” 改为 “最少加几个石子”。
然后可以 DP:设 fi,jfi,j 表示考虑了前 ii 个位置,位于自动机的节点 jj 上的方案数。
对于 ai≥8ai≥8 的情况是与 ai=8ai=8 相同的。
直接转移即可。
时间复杂度 O(nS)O(nS),其中 S=8765S=8765。
11.Range Minimum Sum
放到笛卡尔树上考虑,首先一个点都不删的答案是好求的:
考虑删掉一个点后的影响:
- 对于祖先节点,影响可以一遍 Dfs 求出。
- 对于儿子节点,他们子树内部的贡献是不变的。但是左右儿子要合并起来。发现合并的是左儿子的右链,右儿子的左链,所以暴力归并算贡献即可。
时间复杂度 O(n)O(n)。
12.Heartbeat
首先 nn 的位置把整个序列分成了两部分,左边的部分只有前缀最大值,右边的部分只有前缀最小值,两边的计算是类似的。
首先我们算出 fi,j,kfi,j,k 表示 ii 个元素的排列,有 jj 个前缀最大值、kk 个上升位置的方案数。
考虑如何转移。这种一般是考虑插一个元素。这里如果是插最大值的话,全局最大值的个数会减少。所以我们考虑插最小值:
- 最小值插到开头:fi,j,k→fi+1,j+1,k+1fi,j,k→fi+1,j+1,k+1。
- 最小值插到结尾:fi,j,k→fi+1,j,kfi,j,k→fi+1,j,k。
- 最小值插到上升的间隙中:fi,j,k×k→fi+1,j,kfi,j,k×k→fi+1,j,k。
- 最小值插到下降的间隙中:fi,j,k×(i−1−k)→fi+1,j,k+1fi,j,k×(i−1−k)→fi+1,j,k+1。
然后记 Li,jLi,j 表示 ii 个元素有 jj 个上升位置时前缀最大值的贡献,Ri,jRi,j 表示 ii 个元素有 jj 个上升位置时后缀最小值的贡献,这两个数组都能通过 ff 数组计算出来:
右式中 jj 加了 1 是因为要加上 nn 的贡献。
记 ansi,jansi,j 表示 长度为 ii 的排列有 kk 个上升位置时前缀最大值和后缀最小值的贡献。
则 ansans 可通过 L,RL,R 计算出:
这是个二维卷积的形式,先改写一下:
ansans 中第二维的 +[i>0]+[i>0] 可以通过对 LL 提前处理消掉。
这个直接做是 O(n4)O(n4) 的。
之后有两种处理方法。
sol1
这里我们相当于做了 O(n2)O(n2) 次 O(n2)O(n2) 的多项式乘法,可以通过转成点值变成 O(n2)O(n2) 次 O(n)O(n) 的点乘,这样时间复杂度就是 O(n3)O(n3) 的了,不难注意到 ansans 是 n−1n−1 次多项式。
算完点值以后直接拉插插出每项系数即可。
时间复杂度 O(n3)O(n3)。
sol2
直接看官方做法把。
13.P8349 SDOI/SXOI2022 整数序列
调不出来了 /ll
首先对出现次数根号分治,记阈值为 BB。
对于两个小块,可以把有用的位置拉出来暴力,时间复杂度 O(qB)O(qB)。
对于两个大块,可以暴力然后记忆化,时间复杂度 O(n2B)O(n2B)。
对于一个大块和一个小块,离线处理。对于每个小块元素的连续段,可以找出他前后的连续段长度个大块元素,不难发现只有这些事有用的,然后暴力即可。时间复杂度 O(qB)O(qB)。
平衡一下,时间复杂度为 O(n√q)O(n√q)。
14.P5047 Ynoi2019 模拟赛 Yuno loves sqrt technology II
首先有朴素的莫队 O(n√mlogn)O(n√mlogn) 做法。
先研究右端点的移动。
记端点从 (l,r−1)(l,r−1) 移动到 (l,r)(l,r) 的影响为 f(l,r,r)f(l,r,r) 表示 (l,r−1)(l,r−1) 中比 arar大的数的个数。
发现贡献有可差分性,不妨将他变为 f(1,r,r)−f(1,l−1,r)f(1,r,r)−f(1,l−1,r),分别去做。
首先 f(1,r,r)f(1,r,r) 这个是好解决的,只有 O(n)O(n) 种本质不同的询问,可以扫描线树状数组求出,时间复杂度 O(nlogn)O(nlogn)。
对于 f(1,i,j)f(1,i,j) 这类贡献,不难发现只有 O(n√m)O(n√m) 个(端点移动次数),所以对 ii 这一维扫描线,每次查询大于 ajaj 的数的个数。这部分有 O(n)O(n) 次单点改,O(n√m)O(n√m) 次前缀查,可以根号平衡。
但发现空间不够,原因在于第二类贡献有 O(n√m)O(n√m) 个。
但是我们发现,左端点相同时右端点的移动是一段区间,且只有 O(m)O(m) 个,所以直接存区间就行了。
这样就做到了时间复杂度 O(n√m)O(n√m),空间复杂度 O(n+m)O(n+m)。
15.AtCoder Beginner Contest 366
https://www.cnblogs.com/definieren/p/18353652
16.Codeforces Round 965 (Div. 2)
https://www.cnblogs.com/definieren/p/18353122
17.AtCoder Regular Contest 182
https://www.cnblogs.com/definieren/p/18354900
18.EPIC Institute of Technology Round August 2024 (Div. 1 + Div. 2)
https://www.cnblogs.com/definieren/p/18361339
19.Museums Tour
建分层图,缩点,然后 DP。
时间复杂度 O(nd)O(nd)。
20.D. Perishable Roads
注意到关键应该是最短的边。
发现答案的树的形态应该是形如:根和最短的边有一条链连接,最短的边下挂着个菊花。
现在的关键是找这一条链。
发现如果链上的边依次是 e1,e2,⋯,eme1,e2,⋯,em,则 ∀i<m−1,ei>ei+1∀i<m−1,ei>ei+1。
因为如果存在 ei≤ei+1ei≤ei+1,那么我们可以把 ei+1ei+1 换成任意一条连向最短边的路径,这样答案会更优。
对于最后一条边,如果 em−1>emem−1>em,那么它的贡献是 emem,否则是 em−1em−1。
现在我们的答案是 ∑iei+min edge×(n−1−m)∑iei+min edge×(n−1−m),把 −m−m 放到前面的求和里,得到:
这样根据刚才的分析,先将每条边的边权减去 min edgemin edge,将每个点的初值赋成 2minjwi,j2minjwi,j 然后跑最短路即可。
时间复杂度 o(n2)o(n2)。
21.P1402 酒店之王
简单题。拆一下点随便连就行。
22.F. Special Edges
卡不过去,就当过了把 /ng
最大流等于最小割,所以 O(2k)O(2k) 枚举把这 kk 条边选与不选的最小割都求出,然后询问时拼一下即可。
23.I. Marbles
无源汇上下界可行流。
1 操作就把新建点,连 [0,n][0,n] 的边。
2 操作就向起始点连 [0,1][0,1] 的边。
3 操作就新建一个点连 [l,r][l,r] 的边。
最后再向初始点连一边即可。
24.E. ALT
建模是简单的:源点向每条路径连流量为 1 的边,路径向每个点连流量为 +∞+∞ 的边,每个点向汇点连流量为 11 的边,这样最小割即为答案。
边数太多,考虑优化建图。
有以下几种方式:倍增、树剖加线段树等。
然后就做完了。
25.F. Making It Bipartite
首先如果 aiai 是 ajaj 的因数,就连一条 i→ji→j 的边。
发现问题等价于删多少个点是的最长链不超过 2。
这个是切糕,做完了。
26.P3227 HNOI2013 切糕
典题。
27.P6054 RC-02 开门大吉
和切糕一样,注意边要连全。
28.P4248 AHOI2013 差异
建出 SA 后统计每个 htihti 作为区间最小值的出现次数。
29.P2178 NOI2015 品酒大会
建 SA,然后在 htht 数组的笛卡尔树上统计答案。
30.P2408 不同子串个数
。
31.P1117 NOI2016 优秀的拆分
求出 fifi 表示以 ii 结尾的 AAAA 的数量,gigi 表示以 ii 开头的 AAAA 的数量,则:
现在的问题是求 ff 和 gg,我们只关注求 ff 因为求 gg 和把 ss 翻转后求 ff 是等价的。
考虑枚举 AAAA 中 AA 的长度 lenlen,并以之为间隔做标记。
我们依次考虑相邻两个标记之间的能作为 AAAA 的两个 AA 之间的间隙的位置的数量。
分别求一和正向和反向的 lcplcp,它们的交即为答案。
细节可能比较多。时间复杂度 O(nlogn)O(nlogn)。
32.P3181 HAOI2016 找相同字符
先建两个串拼起来建 SA,然后答案是两个串各选一个位置 LCP 的和,笛卡尔树上算一算就行。
33.P3804 【模板】后缀自动机(SAM)
/fendou
34.E. Cool Slogans
首先发现如果对于相邻的两个选的串,可以将他们没有互相匹配的后缀删掉,这样就得到了 sisi 一定是 si+1si+1 的后缀。
建出 SAM,在 parent 树上自上而下 DP。
设 fifi 表示当前在 ii 节点最长的序列长度,gigi 表示在长为 fifi 时最后一个元素的最小节点。
线段树维护 endposendpos 集合后转移是简单的。
35.P4770 NOI2018 你的名字
先考虑 l=1,r=|S|l=1,r=|S|。
对 SS 和 TT 分别建 SAM。
对于 TT 的每个前缀的所有后缀,满足在 SS 中没出现过的的一定一段前缀。
所以考虑枚举 TT 的每个前缀,维护当前在 SS 上匹配的点和匹配长度,每次前缀长度 +1 时能匹配则匹配,否则暴力跳父亲即可得到每个前缀的最长的没有在 SS 中出现的后缀的长度。
最后对于每个在 SS 中出现的前缀的后缀,将它的后缀全部设为出现过然后在 SAM 上统计答案即可。
再考虑一般的情况。
第一个问题我们不能暴力跳父亲了,因为 SS 只保留了 [l,r][l,r] 的区间,所以一个节点上的 endposendpos 集合不一定相同。正确的做法是维护匹配长度 lenlen,不能匹配则将 lenlen 减一后再尝试匹配,若 lenlen 已经小于 minlenpminlenp,那么就跳父亲。
第二个要解决的问题是我们无法判断能不能走转移边。这个可以线段树合并维护 endposendpos 集合后简单判断。
其余部分与 l=1,r=|S|l=1,r=|S| 的情况基本一致。
时间复杂度 O((|S|+∑|T|)log|S|)O((|S|+∑|T|)log|S|)。
36.P6139 【模板】广义后缀自动机(广义 SAM)
/fendou
37.P4482 BJWC2018 Border 的四种求法
可以用基本子串字典做到 O(nlogn)O(nlogn),但是我在练 SAM。
问题等价于找一个 pos∈[l,r]pos∈[l,r],满足 lcs(pos,r)≥pos−l+1lcs(pos,r)≥pos−l+1。
建 SAM,求 lcslcs 就可转化为两点的 lcalca。
考虑离线下来倒着扫 i:n→1i:n→1,同时维护一个未解决的询问的集合,每次将还没有被解决的询问中答案为 ii 的询问删掉,然后将右端点为 ii 的询问加入集合中。
这样只要我们支持每次 O((1+应被删除的询问个数)polylog(n))O((1+应被删除的询问个数)polylog(n)) 地将应被删除的询问删除,O(polylog(n))O(polylog(n)) 地将每个询问加入,时间复杂度就是对的。
先考虑怎么暴力做。就是不断跳父亲(枚举 lcalca),每次将子树每的询问 check 一遍。
考虑树剖优化这个过程,模拟树剖求 lcalca 的过程。
每次加入询问的时候,跳重链,并把询问挂到每次跳到的点上。
尝试用 ii 删除询问的时候,ii 不断跳重链。不妨设在同一条重链上,ii 跳到的点是 uu,询问的点跳到的点是 vv,对他们的深度分类讨论一下:
Case1: depu≥depvdepu≥depv
这也就是说 lca=vlca=v,此时应有:
线段树叶子处开个 set
维护 lenv+llenv+l 的最大值和询问编号即可。
Case2: depu<depvdepu<depv
这也就是说 lca=ulca=u,此时应有:
线段树叶子处开个 set
维护 1−l1−l 的最小值和询问编号即可。
删除一个询问可以使用标记懒惰删除。
这样我们就做到了均摊 O((n+q)log2n)O((n+q)log2n)。
为什么我写了 9K + /tuu
38.P8150 再会 | Sayounara
根本想不到 /ll
找到最小值位置后就能通过 O(n)O(n) 次操作得出答案,所以目标是找最小值。
考虑三分,拿一个 vector 存当前的分治区间,记其为 [l,r)[l,r),记两个三等分点分别为 p1,p2p1,p2。
此时区间被分成 [l,p1)[l,p1),[p1,p2)[p1,p2),[p2,r)[p2,r)。
每次通过询问得到:x=query(l,p2−1)−query(l,p1−1),y=query(p1,r−1)−query(p2,r−1)x=query(l,p2−1)−query(l,p1−1),y=query(p1,r−1)−query(p2,r−1)。
也即:x=mini∈[l,p2)ai−mini∈[p1,p2)ai,y=mini∈[p1,r)ai−mini∈[p2,r)aix=mini∈[l,p2)ai−mini∈[p1,p2)ai,y=mini∈[p1,r)ai−mini∈[p2,r)ai。
通过细致的分类讨论可以得出最小值在哪个区间中,这样就可以以 O(logn)O(logn) 的代价求出最小值。
39.D - 軍艦ゲーム
设 fu,ifu,i 表示在点 uu,生命值为 ii 走到 nn 的期望步数。
转移为:
发现唯一使转移有后效性的元素是 fi,Hfi,H,考虑对它动一些手脚。
二分 f1,Hf1,H 的值 AA,然后按上面的转移,得出新的 f1,Hf1,H 的值 g(A)g(A),然后调整二分的上下界。
不难通过归纳证明 g′(A)≤1g′(A)≤1,也就是说 (g(A)−A)′≤0(g(A)−A)′≤0,也就是说有单调性,可以二分。
时间复杂度 O(nhlog1ϵ)O(nhlog1ϵ)。
40.P9144 THUPC 2023 初赛 最后的活动
首先显然可以爆搜+迭代,然后把迭代换成上一个题的二分就对了。
时间复杂度 O(2nmlog1ϵ)O(2nmlog1ϵ)。
41.P9073 WC/CTS2023 楼梯
自然可以想到维护右下的轮廓线,1 表示向下的边,0 表示向左的边,现在的目的是找到一个形如 0...1
的子串,使得它的长度为 q+1q+1。
前三个操作可以平衡树简单维护,现在要做的就是查询。
考虑把 i≡1(modq)i≡1(modq) 的位置 ii 单独拉出来,因为第一个位置一定是 1,最后一个位置一定为 0,所以除非楼梯是空的,一定可以找到相邻的两个位置使得他们为 10。
考虑一个类似二分的东西,每次找到 midmid,如果 midmid 位置是 0,就向左逼近,否则向右逼近,这样就会一直满足条件。
时间复杂度 O(nlognlogV)O(nlognlogV)。
42.P5319 BJOI2019 奥术神杖
卡精度。。。懒得喷。
感觉不被关键词提示的话做不出来。
首先肯定要对咒语建 AC 自动机然后跑 DP 啥的。
先取个 lnln,然后可以化成分数规划的形式,DP 就好了。
时间复杂度 O(nslog(ϵ−1V))O(nslog(ϵ−1V))。
43.Chips on a Board
自己想了个很蠢的莫队+trie。。。关键词提示后才会 O(nlogn)O(nlogn)。
这显然和 Nim 游戏是一样的,所以要求的就是区间到左端点距离的异或和。
考虑倍增维护,每次倍增的时候加上最高位的贡献即可。
时间复杂度 O(nlogn)O(nlogn)。
44.CF1523H Hopping Around the Array
跳的时候一定是跳到 ai+iai+i 最大的位置,我们称其为跳一步。
一眼倍增。设 fi,j,kfi,j,k 表示从 ii 开始跳,跳了 2j2j 步,删了 kk 个数跳到的位置和再跳一步能跳到的范围。
然后倍增即可,时间复杂度 O(nk2logn)O(nk2logn)。
45.P6406 COCI2014-2015#2 Norma
扫描线线段树,信息和标记随便设计一下就好。
时间复杂度 O(nlogn)O(nlogn)。
46.P3350 ZJOI2016 旅行者
分治最短路板子。
47.CFgym103409H Popcount Words
首先的思路是将询问串建 AC 自动机,然后将原串的每个前缀所在的点打上标记,答案为子树和。
现在的问题是如何将原串的每个前缀所在的点打上标记。
我们不妨设这个 popcount 串是从 0 开始的。
分析一下发现可以通过如下的方式递归构造出来:
- 初始 s=0s=0。
- 记 rev(s)rev(s) 表示将 ss 按位取反后得到的字符串,那么有:s′=s+rev(s)s′=s+rev(s)。
这看着就很倍增!记 fi,j,kfi,j,k 表示从节点 ii 开始匹配 s[k⋅2j,(k+1)⋅2j+1−1)s[k⋅2j,(k+1)⋅2j+1−1),匹配完后能到哪个点,其中 k∈{0,1}k∈{0,1},这个可以通过下面的式子简单预处理:
现在考虑怎么用 O(logn)O(logn) 个 ff 把区间 [l,r][l,r] 凑出来。
考虑用形如 [2i,2i+1)[2i,2i+1) 这样的区间把 [l,r][l,r] 拼起来,现在的问题就是如何知道它们是否翻转,这个可以直接判断 parity(l)parity(l)。
这样我们就实现了把 [l,r][l,r] 用 O(logn)O(logn) 个区间拼起来。
现在的问题是确定每个位置被经过了多少次。记 gu,j,kgu,j,k 表示从点 uu 开始匹配 s[k⋅2j,(k+1)⋅2j+1−1)s[k⋅2j,(k+1)⋅2j+1−1) 所经过的点被匹配的次数,初始值可以通过刚才的倍增得到。
现在考虑怎么下传经过次数,就是将 jj 的出现次数更新到 j−1j−1 上去。
这部分是简单的:
最后一个点的经过次数就是 gu,0,0+gu,0,1gu,0,0+gu,0,1,统计即可。
时间复杂度 O((n+∑|s|)logV)O((n+∑|s|)logV)。
48.ARC150F Constant Sum Subsequence
首先的思路是设 fifi 表示凑出 sum=isum=i 的序列的最短前缀。
如果记 pre(i,x)pre(i,x) 表示 ii 前面最大的 jj 满足 aj=xaj=x,suf(i,x)suf(i,x) 表示 ii 后面最小的 jj 满足 aj=xaj=x,那么转移为:
现在的问题是优化这个转移。
有一个重要但是比较显然的观察:fifi 单调不降。
考虑通过分治的方式来寻找最优决策点。
现在的分治区间是 [l,mid][l,mid],我们已经知道了 [l,mid][l,mid] 的 DP 值,现在的问题是如何用他们更新 [mid+1,r][mid+1,r] 的 DP 值。
枚举在后面添加的数 ii,发现我们可以按 ii 的序列中的出现位置把 f[l,mid]f[l,mid] 分成若干段,且对于相邻的两段 [l1,r1][l1,r1] 和 [l2,r2][l2,r2],有 ∀j∈[l1,r1],suf(fj,i)<l2∀j∈[l1,r1],suf(fj,i)<l2。
所以根据前面的单调性,只有最后一段是有用的,找出这一段的最前面的 ff 更新即可。
时间复杂度 O(SlogSlogn)O(SlogSlogn)。
49.P8231 AGM 2022 资格赛 农场
整体二分,时间复杂度 O((n+q)lognlogT)O((n+q)lognlogT)。
50.CF1217F Forced Online Queries Problem
强制在线和没有没啥区别,直接线段树分治。
51.CF833D Red-Black Cobweb
显然要点分治。
考虑当前有两条根链,他们权值分别为 (c0,c1,prod)(c0,c1,prod) 和 (c′0,c′1,prod′)(c′0,c′1,prod′),其中 c0c0 表示白边条数,c1c1 表示黑边条数,prodprod 表示边权乘积,prod×prod′prod×prod′ 能贡献到答案当且仅当:
移项可得:
发现至少满足一个,所以用满足第一个的除以不满足第二个的即可。
时间复杂度 O(nlog2n)O(nlog2n)。
52.P4886 快递员
先随便取一个点当根,然后计算出答案,并将取到最大距离的点对存下来。
考虑什么时候向子树走能不能减小答案:
- 存在一个最大的点对跨过当前钦定的根。
- 存在两个不同的商品在不同的子树内。
发现除了这两种情况,能走的子树是固定的。
所以类似点分治,每次走到对应子树的重心即可。
时间复杂度 O(mlogn)O(mlogn)。
53.P8907 USACO22DEC Making Friends P
考虑一个延时连边,就是每次我们把 uu 的连向的点连成完全图时,我们只将其中编号最小的点向其他点连边,其他的边会再后面一起连。
直接做是 O(n2)O(n2),启发式合并即可做到 O(nlog2n)O(nlog2n)。
54.CF566C Logistical Questions
不妨记 f(u)=∑nv=1Distance(v,u)32wvf(u)=∑nv=1Distance(v,u)32wv 表示以 uu 为根时的答案。不难发现,随着 uu 距离真正的带权重心的减少,ff 也是在不断变小的。
考虑通过类似点分治的方式找出带权重心。
首先钦定一个点当根,现在我们要知道的是真正的的带权重心在哪个儿子的子树中。根据上面的结论,至多存在一个儿子满足 f(v)<f(u)f(v)<f(u),这个儿子就是我们要选的点。
考虑记 Δ(v)Δ(v) 表示向 vv 的子树走 ϵϵ 的距离后 ff 的变化量。根据求导可得:
这个可以暴力算出,然后挑选能让答案减少的子树走即可。
时间复杂度 O(nlogn)O(nlogn)。
55.CF715C Digit Tree
直接点分治,两端拼起来的时候要判 v1×10len2+v2≡0(modM)v1×10len2+v2≡0(modM),这个可以把同类的放到一起变成 v1+v2×10−len2≡0(modM)v1+v2×10−len2≡0(modM)。求逆元要用扩欧。
时间复杂度 O(nlogn)O(nlogn)。
56.CF471D MUH and Cube Walls
在差分数组上 KMP。
57.CF1344E Train Tracks
考虑对于每个点,如果它在时刻 x1,x2⋯,xkx1,x2⋯,xk 改变了方向,那么就相当于我们要在 (0,x1],(x1,x2],⋯,(xk−1,xk](0,x1],(x1,x2],⋯,(xk−1,xk] 这 kk段时间中都操作一次。
如果我们能对每个点分别求出这些区间,问题就变成了:
有一个无限长的序列,你要给每个位置 ii 填一个 [0,k][0,k] 的数 aiai,满足 ∀i∈[1,k],∃j∈[li,ri],aj=i∀i∈[1,k],∃j∈[li,ri],aj=i。
这个是经典贪心,按左端点排序,维护当前的右端点集合,每次贪心地满足最小的右端点的限制即可。
考虑怎么找这 kk 个区间。仔细观察,发现初始的时候树被剖成了若干条链,每次操作其实就是把 uu 的根链拉出来。
发现这其实就是 LCT 的 access,所以直接 LCT 维护即可,kk 是 O(mlogn)O(mlogn) 级别的。
有一点小细节,就是你点 uu 在 access 的时候不应该把它原本指向儿子的边切掉。
时间复杂度 O(mlog2n)O(mlog2n)。
58.P8528 Ynoi2003 铃原露露
重点在于支配对的构造。
先考虑一组 (u,v,z)(u,v,z) 对答案的影响:
- 若 au<az<avau<az<av:对答案无影响。
- 若 az<au<avaz<au<av:ban 掉 l∈(az,au],r∈[av,n]l∈(az,au],r∈[av,n] 的 (l,r)(l,r)。
- 若 au<av<azau<av<az:ban 掉 l∈[1,au],r∈[av,az)l∈[1,au],r∈[av,az) 的 (l,r)(l,r)。
考虑对于一个 z=lca(u1,v1)=lca(u2,v2)z=lca(u1,v1)=lca(u2,v2),如果有 [u2,v2]∈[u1,v1][u2,v2]∈[u1,v1],那么 (u2,v2,z)(u2,v2,z) 这个三元组是无用的。
也就是说,如果我们固定了 lcalca,那么对于一个点 uu,它一定只会选在其他子树中它的前驱和后继形成支配对。
如果我们在启发式合并的过程中做这个东西,不难发现有用的支配对只有 O(nlogn)O(nlogn) 个。
现在的问题是已知 o(nlogn)o(nlogn) 个支配对,如何算答案。
把点放到二维平面上,问题就变为矩形加,矩形查 0 的个数。
可以扫描线、区间加历史和线段树维护,时间复杂度 O(nlog2n)O(nlog2n)。
59.P9678 ICPC2022 Jinan R Tree Distance and P9058 Ynoi2004 rpmtdq
如果对于 (u1,v1)(u1,v1),(u2,v2)(u2,v2) 满足 u2≤u1<v1≤v2u2≤u1<v1≤v2 且 Distance(u1,v1)≤Distance(u2,v2)Distance(u1,v1)≤Distance(u2,v2),那么 (u2,v2)(u2,v2) 肯定不会对答案产生贡献。此时我们称 (u1,v1)(u1,v1) 支配了 (u2,v2)(u2,v2)。
考虑怎么构造支配对。因为是路径信息,考虑点分治构造。
现在问题变为有若干二元组 (u,depu)(u,depu),称 (u1,v1)(u1,v1) 支配了 (u2,v2)(u2,v2) 当且仅当 u2≤u1<v1≤v2u2≤u1<v1≤v2 且 depu1+depv1≤depu2+depv2depu1+depv1≤depu2+depv2,要找出尽量少的支配对。
仔细思考一下,上面那个条件等价于说 depudepu、depvdepv 是 [u,v][u,v] 中的最小、次小值。
枚举 uu,钦定 uu 是最小值我不会做,但是我会做钦定 uu 是次小值,此时的 vv 一定是 maxdepv≤depu∨v<uvmaxdepv≤depu∨v<uv 或 mindepv≤depu∨v>uvmindepv≤depu∨v>uv。
这也就是说,对于在一次分治中,每个点只会主动产生 2 个支配对,所以支配对个数是 O(nlogn)O(nlogn) 的。
查询就是矩形查 maxmax,扫描线即可。
时间复杂度 O(nlog2n)O(nlog2n)。
60.P5291 十二省联考 2019 希望
首先的第一想法是把包括每个点的答案算出来然后相加对吧,但这样会算重。
但是你发现,对于一组方案, 它能到达的点一定是一个连通块,我们想让它只被算一次。这个可以点边容斥 1=V−E1=V−E。
也就是说,我们要把每个点和每条边的答案算出来相减。
考虑 DP:记 fu,ifu,i 表示选出一个在 uu 子树内且最远点与 uu 距离不超过 ii 的包含 uu 的连通块方案数,gu,igu,i 表示选出一个在 uu 子树内且最远点与 uu 距离不超过 ii 的包含 uu 的连通块的方案数。
转移为:
然后点的贡献为 (fu,Lgu,L)k(fu,Lgu,L)k,u→fauu→fau 这条边的贡献为 (fu,L−1(gu,L−1))k(fu,L−1(gu,L−1))k。
后面的以后再说 /ng
61.P8543 「Wdoi-2」纯粹的复仇女神
考虑每个元素的贡献。
对于 aiai,记以颜色和它相同的以它为最小值的极长区间为 [Li,Ri][Li,Ri],那么它就会对 l∈[Li,i]∨r∈[i,Ri]l∈[Li,i]∨r∈[i,Ri] 的询问产生 aiai 的贡献。
所以问题等价于矩形 chkmax,单点查,扫描线线段树标记永久化 multiset 维护即可。
时间复杂度 O(nlog2n+qlogn)O(nlog2n+qlogn)。
62.CF506D Mr. Kitayuta's Colorful Graph
暴力是枚举每种颜色,并查集,然后枚举每个询问进行查询。
我们把询问 (u,v)(u,v) 挂到被询问次数较少的一个点上,并去重,这样每个点只会被挂 O(√q)O(√q) 个询问(原理同三元环计数),然后暴力即可。
时间复杂度 O(m√q)O(m√q)。
63.P9149 串串题
首先发现,bb 中的元素是一定不能删的,因为删掉以后一定不匹配。
考虑只保留 bb 中的元素 KMP 一遍,一次计算每个匹配的位置的贡献。
对于一个匹配区间 (l,r)(l,r),记其中不在 bb 中的元素个数为 tt,所有不在 bb 中的元素个数为 WW,那么它的贡献为 (W−td−t)(W−td−t)。
时间复杂度线性。
64.P9196 JOI Open 2016 销售基因链
首先正反建 Trie,然后问题就变为了两棵子树求交,这个是 dfn 上二维数点。
时间复杂度 O(∑|S|log∑|S|)O(∑|S|log∑|S|)。
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步