2025.2 暑假专题记录

2025.2 暑假专题记录

主要记录下暑假专题的作业题做法

树型 DP

P.S. 以下常用 u 表示当前节点,v 表示 u 的儿子

P3047

朴素思路是以每个点为根分别统计其答案,时间复杂度 O(n2),无法接受;这启示我们利用其他点的信息,即换根

gi,j 表示 i 子树内与其距离为 j 的点的权值和,显然有转移 gu,j=gv,j1,我们可以通过一次 dfs 求出 g 数组

fi,j 为与点 i 距离为 j 的点的权值和,与点 v 距离为 j 的点包含两部分:

  • v 子树内与其距离为 j 的点,即 gv,j
  • v 子树外与其距离为 j 的点,换句话说是点 u 子树外与其距离为 j1 的点;"子树外"的限制不好处理,可以将其变为 fu,j1 挖去 v 子树对其造成的贡献,即 fu,j1gv,j2

综上,转移为 fv,jgv,j+fu,j1gv,j2

初始值为 fi,0=gi,0=wi,点 i 的答案为 j=0kfi,j

考虑类似扫描线的思想,当 i 逐渐增大,村庄 j(ji) 会在某一时刻需要赔偿,影响范围是一段区间

因此考虑线段树优化 dp;预处理出 sti,edi 表示 i 左边 / 右边最近不能覆盖到村庄 i 的位置,当 iedj 时,若从 [1,stj] 转移则需要对 j 进行赔偿,此时对 [1,stj] 进行一次区间加即可;求 fi 即为对 [1i1] 做一次区间查询

P2279

以下为方便表述,设 u 为当前节点,u1u 的父亲,u2u 的父亲的父亲,v1u 的儿子,v2u 的儿子的儿子

fi,j 表示使用 i 子树中的点,至少覆盖点 i 子树内以及 i 祖先节点到第 j 层所需的最少代价

由于消防局最大覆盖距离为 2,因次 |j| 最大为 2;为了不漏掉用一个点的祖先覆盖该点的情况,j 应可以为负;具体的:

  • fu,2 表示至少覆盖到 u2 这层
  • fu,1 表示至少覆盖到 u1 这层
  • fu,0 表示至少覆盖到 u 这层
  • fu,1 表示至少覆盖到 v1 这层
  • fu,2 表示至少覆盖到 v2 这层

注意状态定义有包含关系,有 fi,2fi,1fi,0fi,1fi,2

对于 fu,2,我们必然要在点 u 设立消防局,已经能覆盖到 v2 这层;因此对于 v1,至少覆盖到 v1 儿子的儿子这层即可,转移为 fu,2fv1,2

对于 fu,1,在 u 设立消防局的情况我们在 fu,2 已经考虑过,因此先令 fu,1min(fu,1,fu,0);现在只考虑在 v1 设立消防局,我们钦定在 v1,x 放,则对于其他 v1 只需至少覆盖到 v1 儿子这层,转移为 fu,1min(fv1,x,2+v1v1,xfv1,1)

对于 fu,0,同理先令 fu,0min(fu,0,fu,1,fu,2);与 fu,1 类似,我们钦定在 v1,x 的子树中放消防局往上覆盖到 u 这层,代价即为 fv1,x,1,其他 v1 只需至少覆盖到它自己这层,转移为 fu,0min(fv1,x,1+v1v1,xfv1,0)

对于 fu,1,先令 fu,1min(fu,1,fu,0,fu,1,fu,2);此时 v1,x 子树中的消防局对其他 v1 没有影响,所有儿子没有区别,只需覆盖到自己这层,转移为 fu,1fv1,0

对于 fu,2,先令 fu,2min(fu,2,fu,1,fu,0,fu,1,fu,2);与 fu,1 类似,v1 只需覆盖到它的儿子这层,转移为 fu,2fv1,1

对于叶子,初始值为 fu,4=fu,3=fu,2=1,非叶子则为 fu,4=1;答案为 froot,0

ABC160F

本质上这个问题是树上拓扑序计数

注意到只要对于点 i 子树内任一点 j,都有 j 子树内 j 最先填 (递归满足即可),这样的填数方案就是合法的

记点 i 的子树大小为 sizi,则对于点 i 子树内的所有填数方案,只有 1sizi 是合法的,因为我们需要保证 i 最先填;那么总合法方案数为 n!sizi

那么问题转化为需要快速求出以每个点为根时的 sizi,考虑换根

fi 为以 i 为根时 sizi 的值;从以 u 为根变为以 v 为根时,sizunsizvsizvn,因此有转移 fvfu×nsizvn×nsizv=fu×nsizvsizv

P4516

考虑如何设计 dp 状态;显然需要一维 i 表示点编号,背包维 j 表示用了多少监听设备;直接做没法转移,考虑增加两维 0/1, 0/1 表示是否在点 i 上放监听设备、点 i 是否被监听

综上,考虑设 fi,j,0/1,0/1 表示以 i 为根的子树中放了 j 个监听设备,点 i 上是否放了监听设备,点 i 是否被监听的方法数

这是一个树上背包,我们按照 fu,i+j,fu,i,,fv,j, 的方式转移

考虑分类讨论转移策略:

  • 对于 fu,i+j,0,0u 自己没放也没被监听,儿子上不能放,且必须已经被监听 (因为从 u 监听的路已经断了);因此转移为 fu,i+j,0,0(fu,i,0,0×fv,j,0,1)
  • 对于 fu,i+j,1,0u 自己放但没被监听,儿子上不能放,且是否已被监听都行;转移为 fu,i+j,1,0(fu,i,1,0×fv,j,0,0/1)
  • 对于 fu,i+j,0,1, u 自己没放但被监听,对之前 u 是否已被监听分类讨论:
    • 若之前未被监听且 v 处放完后被监听,则 v 处必然又放又被监听 (因为无法从 u 监听),转移为 fu,i+j,0,1(fu,i,0,0×fv,j,1,1)
    • 若之前已被监听,则 v 处必然被监听,放不放无所谓,转移为 fu,i+j,0,1(fu,i,0,1×fv,j,0/1,1)
  • 对于 fu,i+j,1,1u 自己放也被监听,同样分类讨论:
    • 若之前未被监听且 v 处放完后被监听,则 v 处必然放,是否已经被监听无所谓,转移为 fu,i+j,1,1(fu,i,1,0×fv,j,1,0/1)
    • 若之前已被监听,则 v 处状态随意,转移为 fu,i+j,1,1(fu,i,1,1×fv,j,0/1,0/1)

初始值为点 u 自己放或不放,即 fu,0,0,0=fu,1,1,0=1;最终只需要 root 被监听,答案为 froot,k,0,1×froot,k,1,1

实现时注意对每个 v,在转移到 u 前先缓存一份 u 的当前答案防止转移混乱;加上 siz 的优化后时间复杂度是 O(nk)

P4284

由于每个点贡献都是 1,期望和实际上就是概率和

与第一道题有点像,考虑换根,第一次处理子树内贡献,第二次处理子树外贡献

不妨直接根据题意设 fi 表示点 i 通电的概率

先考虑子树内;那么点 u 通电有两种可能:

  • u 自己开始就通电
  • u 的某个儿子 v 通电,顺着 (u,v) 转移过来

注意若事件 A 发生的概率为 P(A),事件 B 发生的概率为 P(B),则两者至少发生一个的概率为 P(A)×(1P(B))+P(B)×(1P(A))+P(A)×P(B)=P(A)+P(B)P(A)×P(B)

因此不妨初始设 fuqu;则转移为 fufu+fv×p(u,v)fu×fv×p(u,v)

再考虑子树外;一种显然的想法是直接用第一次求出的 fu 反回来更新 fv,但这是不正确的,因为这里的 fu 包含 fv 对其的贡献,相当于 fv 自己转移到自己,显然是错的;因此我们考虑挖掉 fvfu 造成的贡献,再转移回 fv

不妨认为第一次求出的 fu 最后一个从 fv 转移 (换句话说,vu 的最后一个儿子),记转移前 fu=fupre,转移后 fu=fulast,易知 fulast=fupre+fv×p(u,v)fupre×fv×p(u,v),可以反解出 fupre=fulastfv×p(u,v)1fv×p(u,v) (P.S. 注意特判 fv×p(u,v)=1);我们用 fupre 按照第一次的方式更新 fv 即可

答案为 fi

P9745

对于与异或有关的题,常见的想法是拆位;本题涉及断边操作,考虑将与当前点直接相连 / 非直接相连的连通块价值刻画进状态内

fi 为点 i 子树内的答案,gi,j,k 为以 i 为根的子树内断掉若干边,与 i 相连的连通块价值在二进制下第 jk 时,不与 i 相连的所有连通块的价值乘积和

我们有 fu=i=063(2i×gu,i,1) (对于 gu,i,0,其已经在 u 子树内某点为根时统计过)

考虑如何转移;对于 u 与儿子 v,分类讨论 gu,i,0/1 的来源:

  • 对于 gu,i,0

    • 不断 (u,v),可以由自己的 0 异或上儿子的 0,或由自己的 1 异或上儿子的 1 得来
    • (u,v),只能由自己的 0 得来

    综上,gu,i,0gu,i,0×(gv,i,0+fv)+gu,i,1×gv,i,1

  • 对于 gu,i,1

    • 不断 (u,v),可以由自己的 0 异或上儿子的 1,或由自己的 1 异或上儿子的 0 得来
    • (u,v),只能由自己的 1 得来

    综上,gu,i,1gu,i,0×gv,i,1+gu,i,1×(gv,i,0+fv)

初始值为若 aui 位为 1gu,i,1=1,反之 gu,i,0=1;答案为 froot

P3523

咕咕咕。感觉没太理解。

CF1394D

首先,对于边 (u,v),若 bubv 则这条边的方向确定

题目转化为给未定向的边定向,使得总权值和最小

从整体上不太好刻画,我们考虑拆贡献;对于点 u,记其入度为 inu,出度为 outu,一条经过它的链要么对 inu 贡献 1,要么对 outu 贡献 1 (因为 u 可能是链头或链尾);因此点 u 的贡献为 max(inu,outu)×au

考虑调整法;我们在一开始先强行令未定向边都从儿子指向父亲,再逐个调整

fu,0/1 表示强制 ufau / 强制 ufauu 子树内的答案

注意到对于 v,我们必然贪心地选 fv,1fv,0 最小的进行更改,直接模拟,边改边更新即可

P8867

显然对于一个边双,爱咋建咋建,肯定合法;这启示我们先缩边双,将原图转化为一棵树

fi,0/1 表示点 i 子树内放不放军营的方案数;不过对于点 u,点 v 的军营是否已经合法,是否需要连到 u,好像都不太清楚,没法转移

因此我们更新状态,设 fi,0/1 表示点 i 子树内放不放军营,且若放则必须连到 i 的方案数

对于点 u,记 u 代表的边双点数为 Vu,边数为 Eu,依次对每个儿子考虑转移:

  • 对于 fu,0,显然有 fu,0fu,0×fv,0
  • 对于 fu,1,分类讨论 u 之前放没放军营:
    • u 之前没放,则 v 放,(u,v) 边必须看守,fu,1fu,0×fv,1
    • u 之前放,则 v 可放可不放,不放则 (u,v) 边可看可不看,fu,1fu,1×(fv,0×2+fv,1)

初始值为 fu,0=2Eufu,1=2Eu+Vu2Eu

此时答案就是 froot,0/1 么?如果直接算,相当于强制 root 子树内的每个军营都连到 root,无论 root 是否有军营;这显然是不对的

因此我们对每个点 u 都统计一遍,每次强制 u 建军营,u 子树外的点全部不建军营;先处理出点 u 子树内的边数 Esizu,则答案为 (fu,1×2EsizrootEsizu1)

ARC098D

咕咕咕。放到以后刷 Kruskal 重构树的 blog 里面吧。

DP 优化

P2605

首先考虑朴素 dp

fi,j 表示前 i 个村庄建立 j 个基站的最小代价

显然有转移 fi,j=ci+min(fk,j1+cost(k,i)),其中 cost(k,i) 表示村庄 ik 中需要的赔偿费用,时间复杂度 O(n2k),无法接受

注意到第二维的 j 可以去掉,提到最外面枚举即可

考虑类似扫描线的思想;预处理出 sti,edi 表示点 i 左侧 / 右侧最近的覆盖不到 i 的位置,当 iedj 时将村庄 j 的赔偿费用加进去,形如对 [1,stj] 的区间加

fi 即为对 [1,i1] 的区间询问;线段树维护即可

P3628

fi 表示前 i 个点的答案

容易得到转移 fi=fj+F(sisj)si 为前 i 个点的前缀和,F(x) 为题目中定义的二次函数

不妨设 j>kj 的转移优于 k,则有:

fj+a(sisj)2+b(sisj)+c>fk+a(sisk)2+b(sisk)+c

fj2asisj+asj2bsj>fk2asisk+ask2bsk

(fj+asj2bsj)(fk+ask2bsk)>2asi(sjsk)

g(x)=fx+asx2bsx,则有

g(j)g(k)2a(sjsk)>si

我们将 si 看做横坐标,g(i) 看做纵坐标,则每个 i 在坐标系中对应一个点,原式可看做斜率;

对于坐标系中三点 P1,P2,P3,若 P2 可能最优,则有 k(P1,P2)sik(P2,P3);因此我们要维护一个斜率递降的点集,可以直接单调队列,队首就是最优转移点

P4360

sdi 为距离的后缀和,swi 为重量的前缀和,s=(wi×sdi) 表示总费用

fi 为在点 i 放第二个锯木厂的最小代价,容易得到 fi=minj=1i1(sswj×sdj(swiswj)×sdi),即先将 1j 的木材运到 j,再将 j+1i 的木材运到 i

不妨设 j>kj 的转移优于 k,则有:

sswj×sdj(swiswj)×sdi<sswk×sdk(swiswk)×sdi

sdi×(swjswk)<swj×sdjswk×sdk

g(x)=swx×sdx,则有

g(j)g(k)swjswk>sdi

同理对于坐标系中三点 P1,P2,P3,若 P2 可能最优,则有 k(P1,P2)sdik(P2,P3);因此我们维护一个斜率递降的点集,单调队列即可,队首就是最优转移点

P3349

暴力状压做法即设 fi,j,S 表示点 ij,子树内使用的编号集合,时间复杂度 O(3nn3)

瓶颈在于枚举子集,考虑优化这一过程;注意到记录 S 的原因是需要保证 1n 刚好出现一次,尝试扔掉这个性质

这启示我们容斥;枚举 S,先钦定填的编号是 S 的子集,再减去重复的情况

fi,j 表示点 ij,子树内的方案数,转移为 fu,jfv,k,其中 jS,kS,(j,k)E,时间复杂度 O(3n2n)

CF383E

注意到题目很像 SOS dp,尝试往相关方向转化

设当前元音字母集合为 S,考虑转化为求补集,即求所有字母为 S 的子集的单词数量

f(S) 为字母集合为 S 的单词数量,即求 g(S)=TSf(T),这是 SOS dp 的经典形式

S 的每位看作数组的一维,则 TSi(TiSi),因此子集求和等价于对数组做高维前缀和

实现上,我们先枚举每位 i,再枚举集合 S

  • Si=1,令 fSfS+fS2i (即将该位的 0 累加到 1 上)
  • Si=0,无需另外做前缀和,无事发生

记第 i 个字符串形成的集合为 Ssi,初始值为 fSsi=1,答案为 (nfS)2

数学

P2568

即求

pprimei=1nj=1n[gcd(i,j)=p]

=pprimei=1npj=1np[gcd(i,j)=1]

=pprime(1+i=1np(2j=1i[gcd(i,j)=1]))

这里 1 是因为 i=1,j=1 会被算两次

=pprime(1+2i=1npφ(i))

筛出 φ(i) 做前缀和即可

P2257

不妨设 nm,即求

pprimei=1nj=1m[gcd(i,j)=p]

=pprimei=1npj=1mp[gcd(i,j)=1]

此时由于 n,m 不同,无法直接化为 φ(i) 的形式

对于 [gcd(i,j)=1],还有一个常见变形是利用莫比乌斯反演化为 d|gcd(i,j)μ(d)

=pprimei=1npj=1mpd|gcd(i,j)μ(d)

交换下求和顺序

=pprimed=1npμ(d)i=1npdj=1mpd1

=pprimed=1npμ(d)npdmpd

发现后面挂着的 npdmpd 影响我们预处理,不妨设 k=pd,考虑将 k 提到前面去

=k=1nnkmk(p|k,pprimeμ(kp))

此时后面就可以预处理了,筛出 μ(i) 后枚举质数 p,累加到其所有倍数上即可

P4588

直接模拟的问题在于 M 可能非质数,有可能不存在逆元

考虑单独将 xM 不互质的部分 (相同的质因子) 拉出来,维护其幂次,其余部分正常做即可

P3911

Ai,Aj 不好维护,考虑将"在下标上统计"转化为"在值域上统计"

cii 这一值的出现次数,nmaxAi,即求

i=1nj=1n(ci×cj×lcm(i,j))

考虑将 lcm 变为我们较为熟悉的 gcd

=i=1nj=1n(ci×cj×ijgcd(i,j))

=k=1ni=1nj=1n([gcd(i,j)=k]×ci×cj×ijk)

=k=1ni=1nkj=1nk([gcd(i,j)=1]×ci×k×cj×k×i×k×j×kk)

=k=1ni=1nkj=1nk([gcd(i,j)=1]×ci×k×cj×k×i×j×k)

变成莫比乌斯反演的形式

=k=1ni=1nkj=1nkd|gcd(i,j)μ(d)×(ci×k×cj×k×i×j×k)

交换求和顺序

=k=1nd=1nkμ(d)i=1nkdj=1nkd(ci×k×d×cj×k×d×i×d×j×d×k)

=k=1nd=1nkμ(d)×(d2i=1nkdj=1nkd(ci×k×d×cj×k×d×i×j×k))

kd=T 以简化式子

=k=1nd=1nkμ(d)×di=1nTj=1nT(ci×T×cj×T×i×j×T)

=k=1nd=1nkμ(d)×di=1nTj=1nT(ci×T×cj×T×i×j×T)

把后面的 T 提到最前面

=T=1nT(d|Tμ(d)×d)i=1nTj=1nT(ci×T×cj×T×i×j)

=T=1nT(d|Tμ(d)×d)(i=1nTci×T×i)2

筛出 μ(i),可以预处理出 d|Tμ(d)×d,时间复杂度 O(nlnn)

枚举 T,后面暴力算,时间复杂度也是 O(nlnn),于是总复杂度 O(nlnn)

AGC003D

这是一个抽象做法

对于本身就是完全立方数的数,最多选 1 个,剩下的扔掉不管

考虑对于每个 si 求出其"共轭数" (相乘为完全立方数的数),对于每对共轭数,贪心地选出现次数多的

数据范围不支持我们直接分解质因数……么?注意到 nlnn10000,平均分解次数不会很大,筛出 n 以内质数后大力分解质因数,拿掉立方因子,顺便算一下共轭数即可

字符串

P4555

li 表示以 i 为结尾的最长回文串长度,ri 表示以 i 为开头的最长回文串长度,答案即为 maxli+ri+1

考虑 manacher;记新串 (如 aba #a#b#a#) 上第 i 位的最长回文半径为 di,其代表的最长回文串为 [idi+1,i+di1],原串长度为 di,我们令 li+di1max(li+di1,di)ridi+1max(ridi+1,di)

不过此时直接算答案会有问题;我们只是根据每位的最长回文串长度更新了 li,ri,没有覆盖到较短的回文串

比如 ababa #a#b#a#b#a#,以第 3a 为中心的回文串除了 #a#b#a#b#a# 还有 #b#a#b#,但我们只用前者更新了 li,ri

因此我们还需要再进行一次递推;回文串向中间挪动一次会少 2 个字符,我们枚举每个字母的位置 i,进行转移 li=li+22ri=ri22

枚举每个 # 的位置 i,答案即为 max(li1+ri+1)

P2870

朴素贪心思路是比较两头字典序,若相同则暴力往中间挪

可以使用哈希优化这一过程,二分头尾最长相同串的长度,做到 O(nlogn)

P9873

114514 串太复杂了,考虑简化为 1, 14, 5, 14

posted @   lzlqwq  阅读(6)  评论(0编辑  收藏  举报
相关博文:
阅读排行:
· 地球OL攻略 —— 某应届生求职总结
· 周边上新:园子的第一款马克杯温暖上架
· Open-Sora 2.0 重磅开源!
· 提示词工程——AI应用必不可少的技术
· .NET周刊【3月第1期 2025-03-02】
点击右上角即可分享
微信分享提示