树形DP
[POI2011] DYN-Dynamite
二分KKK
check(mid):
能否选出mmm个点,使得 ∀i为关键点,Minjisselected{dis(i,j)}≤mid\forall i为关键点,Min_{j\ is\ selected}\{dis(i,j)\}\leq mid∀i为关键点,Minj is selected{dis(i,j)}≤mid
进一步转化问题:
一棵树上选 tottottot 个点,使得∀i为关键点,Minjisselected{dis(i,j)}≤mid\forall i为关键点,Min_{j\ is\ selected}\{dis(i,j)\}\leq mid∀i为关键点,Minj is selected{dis(i,j)}≤mid,最小化 tottottot。若tot≤mtot\leq mtot≤m则 check(mid) 为 true,否则 check(mid) 为 false。
定义点iii被点jjj覆盖,当且仅当disi,j≤middis_{i,j}\leq middisi,j≤mid
假设当前考虑到以xxx为根的子树。
对于在xxx子树内的关键点,它们要么被xxx子树内的点覆盖,要么还等着被xxx子树外的点覆盖。
对于第二种情况,我们需要把问题留到考虑xxx的祖先时再去解决。
设fxf_xfx表示xxx子树内未被覆盖点到xxx的最远距离,
gxg_xgx表示xxx子树内被选择点到xxx的最近距离。
初值:fx=−∞,gx=∞f_{x}=-\infty,g_{x}=\inftyfx=−∞,gx=∞
转移:fx=max{fy+1}f_x=\max \{f_y+1\}fx=max{fy+1},gx=min{fy+1}g_x=\min\{f_y+1\}gx=min{fy+1}
特判:
若fx+gx≤midf_x+g_x\leq midfx+gx≤mid,则xxx子树内所有点都已经被覆盖,fx←−∞f_x\leftarrow -\infinfx←−∞
若fx=midf_x=midfx=mid,则xxx一定要选,fx←−∞,gx←0,tot++f_x\leftarrow -\infin,g_x\leftarrow 0,tot++fx←−∞,gx←0,tot++
若gx>midandx为关键点g_x>mid\ and\ x为关键点gx>mid and x为关键点,把问题留给xxx的父亲解决,fx←max(fx,0)f_x\leftarrow max(f_x,0)fx←max(fx,0)
Code
重建道路
设f[i][j]f[i][j]f[i][j]表示以iii为根的子树,保留jjj个点(包括自己),删去的最小边数
初始化:f[i][1]=son[i]f[i][1]=son[i]f[i][1]=son[i](son[i]son[i]son[i]表示iii有几个儿子)
转移:f[u][j]=max{f(u,j−k)+f(v,k)−1}f[u][j]=max\{f(u,j-k)+f(v,k)-1\}f[u][j]=max{f(u,j−k)+f(v,k)−1}(−1是因为v和u之间相连的那一条边不删)
注意:我们要获得的子树的根并不一定要是整棵树的根节点
Code
城市环路
基环树
如果这道题是出在树上,那就是最大独立集的裸题
设f[i][1/0]f[i][1/0]f[i][1/0]表示选/不选iii ,以iii为根的子树的最大贡献
f[u][1]=∑v∈sonuf[v][0]f[u][1]=\sum_{v\in son_u}f[v][0]f[u][1]=∑v∈sonuf[v][0]
f[u][0]=∑v∈sonumax(f[v][0],f[v][1])f[u][0]=\sum_{v\in son_u}max(f[v][0],f[v][1])f[u][0]=∑v∈sonumax(f[v][0],f[v][1])
考虑在基环树上怎么做:
法一:强制断边
首先把环找出来
对于环上一对相邻点(x,y)(x,y)(x,y),根据题意,x,yx,yx,y不能同时选
- 强制xxx不选,此时yyy可选可不选,断掉边(x,y)(x,y)(x,y)无影响。断边后做树形dp,f[x][0]f[x][0]f[x][0]即为此情况下的答案
- 强制yyy不选,此时xxx可选可不选,断掉边(x,y)(x,y)(x,y)无影响。断边后做树形dp,f[y][0]f[y][0]f[y][0]即为此情况下的答案
- 最终答案=max(f[x][0],f[y][0])max(f[x][0],f[y][0])max(f[x][0],f[y][0])
Code
法二:树形dp+环形dp
博客
Code
[JSOI2008]魔兽地图
这个题的特殊性在于儿子对于父亲节点是有影响的,
所以用f[i][j][k]f[i][j][k]f[i][j][k]表示第iii号装备,其中jjj个被祖先用来合成上层装备,花费kkk元所能获得最大的力量值。
分步转移,第一步先枚举第 iii 号装备合成多少个,第二步再合并子树贡献。
Code
[JSOI2016]最佳团体
分数规划
二分答案midmidmid,问题转化为:
给定一棵根为0的树。每点点权为Pi−mid∗SiP_i-mid *S_iPi−mid∗Si,选定一个点就必须选其所有祖先节点。
问能否取kkk个节点使得取出点的点权和大于零。
设dp[u][j]dp[u][j]dp[u][j]表示以uuu为根的子树,取jjj个节点所带来的最大收益
合并就是经典树形背包
Code
[USACO12FEB]Nearby Cows G
基础换根dp题
f[i][j]f[i][j]f[i][j] 表示 iii 子树内到 iii 距离为 jjj 的点的权值和
g[i][j]g[i][j]g[i][j] 表示 iii 子树外到 iii 距离为 jjj 的点的权值和
Code
CF512D Fox And Travelling
首先,在环中的点一定不会被遍历。
用类似拓扑排序的过程可以把环上的点全部扔掉,剩下的点会构成若干个有根树和无根树,其中有根树的根是树中唯一与环中的点相连的点。
先考虑有根树,设 fi,jf_{i,j}fi,j 表示以 iii 为根的子树中,选 jjj 个点的方案数
转移:fi,j+k=fpi,j×fson,k×(j+kk)f_{i,j+k}=fp_{i,j}\times f_{son,k}\times \binom {j+k}{k}fi,j+k=fpi,j×fson,k×(kj+k)
特别地,fi,sizi=fi,sizi−1f_{i,siz_i}=f_{i,siz_i-1}fi,sizi=fi,sizi−1(根节点必须最后删)
对于无根树,感觉可以钦定最后一个被删的是哪个点,但更简单的方法是直接对每个点为根跑一遍有根树的算法,然后发现选 iii 个点的情况在没被选的 siz−isiz-isiz−i 个点为根的时候会被统计,因此答案要除以 siz−isiz-isiz−i(如果全选是特殊情况,不需要除)
然后就是森林合并答案,就用类似合并子树的方法组合数合并就可以了
Code
CF543D Road Improvement
换根dp
根据套路,
我们设fuf_ufu为修好以uuu为根的子树中的路的方案数
gug_ugu为修好整棵树中除了以uuu为根的子树中的路的方案数
先考虑fuf_ufu怎么求:
设fu,0f_{u,0}fu,0表示uuu子树内无坏边的方案数,fu,1f_{u,1}fu,1表示uuu子树内有坏边的方案数
fu,0=∏v∈sonufv,0,fu,1=∏v∈sonu(fv,0×2+fv,1)−1f_{u,0}=\prod_{v\in son_u} f_{v,0},f_{u,1}=\prod_{v\in son_u} (f_{v,0}\times 2+f_{v,1})-1fu,0=∏v∈sonufv,0,fu,1=∏v∈sonu(fv,0×2+fv,1)−1
发现fu,0=1f_{u,0}=1fu,0=1,又考虑到fu=fu,0+fu,1f_u=f_{u,0}+f_{u,1}fu=fu,0+fu,1,
所以fu=∏v∈sonu(fv+1)f_u=\prod_{v\in son_u}(f_v+1)fu=∏v∈sonu(fv+1)
再考虑gug_ugu:
gu=gfa×ffafu+1+1=gfa×∏x∈sonfa,x≠u(fx+1)+1g_u=\frac{g_{fa}\times f_{fa}}{f_u+1}+1=g_{fa}\times\prod_{x\in son_{fa},x\not=u}(f_x+1)+1gu=fu+1gfa×ffa+1=gfa×∏x∈sonfa,x=u(fx+1)+1
因为逆元不保证存在,所以要记录前缀积和后缀积来避免除法
Code
CF1146F Leaf Partition
博客
CF1016F Road Projects
博客
CF671D Roads in Yusland
博客
CF337D Book of Evil
经典换根dp
设f[u][0]f_[u][0]f[u][0]表示 uuu子树内的点到uuu的最大/次大距离
g[u][0]g_[u][0]g[u][0]表示 uuu子树外的点到uuu的最大/次大距离
CF23E Tree
博客
CF708C Centroids
博客
其他DP
[WC2008] 游览计划
斯坦纳树
模板
斯坦纳树问题:
给出一个有 nnn 个点 mmm 条边的有权无向图,然后选定 kkk 个点,让你求出使这 kkk 个点联通所需的最小代价
求解:
首先,答案的子图一定是树
设 dp[i][S]dp[i][S]dp[i][S] 表示以 iii 为根的一棵树,包含集合 SSS 中所有点的最小代价。
转移:
对于 iii 的度数为 1 的情况,可以考虑枚举树上与 iii 相邻的点 jjj,则
dp(j,s)+w(j,i)−>dp(i,s)dp(j,s)+w(j,i)−>dp(i,s)dp(j,s)+w(j,i)−>dp(i,s)
对于 iii 的度数大于 1 的情况,可以划分成几个子树考虑,则
dp(i,T)+dp(i,S−T)−>dp(i,S)(T⊆S)dp(i,T)+dp(i,S−T)−>dp(i,S)(T\subseteq S)dp(i,T)+dp(i,S−T)−>dp(i,S)(T⊆S)
对于第1种转移,可以想到最短路模型的三角形不等式,对于每一个 SSS ,将图做一次松弛操作即可。具体可以用 dijkstra 或 spfa 实现。
对于第2种转移,枚举子集即可。
如何优秀的枚举子集:
一个非常trivial的做法:
for(int sta=0;sta<=MAX;sta++){for(int s=0;s<=MAX;s++){if(s&sta==s){//to do sth}}
}
时间复杂度 O(4n)O(4^n)O(4n)
更优秀的实现:
for(int sta=0;sta<=MAX;sta++){for(int s=(sta-1)&sta;s;s=(s-1)&sta){//to do sth}
}
时间复杂度 ∑sta2∣∣sta∣∣=∑i=0nCni2i=3n\sum_{sta}2^{||sta||}=\sum_{i=0}^{n}C_{n}^{i}2^i=3^n∑sta2∣∣sta∣∣=∑i=0nCni2i=3n
Code
[COCI2011-2012 6]
SOS DP+容斥
首先发现 mmm 很小,于是直接对于每一个箱子状压
于是问题转化为选若干个数使它们按位或为全集
继续转化一下,把每个箱子取个反,问题就变成了选若干个数使它们按位与为空集
设 g[S]g[S]g[S] 为有多少种选数方案使SSS为选出数的按位与的子集
答案为∑S(−1)∣∣S∣∣g[S]\sum_{S}(-1)^{||S||}g[S]∑S(−1)∣∣S∣∣g[S]
设 f[S]f[S]f[S] 为有多少个箱子,使SSS为其代表的数A[i]A[i]A[i]的子集
g[S]=2f[S]−1g[S]=2^{f[S]}-1g[S]=2f[S]−1
求 f[S]f[S]f[S]:
法一:直接枚举子集
for(int sta=0;sta<=MAX;sta++){for(int s=(sta-1)&sta;s;s=(s-1)&sta){//to do sth}
}
时间复杂度 O(3m)O(3^m)O(3m)
法二:高维前缀和解决这类子集问题
for(int i=0;i<m;i++){for(int s=0;s<(1<<m);s++){if(s&(1<<i)){f[s^(1<<i)]+=f[s];//与标准sos dp方程相比,这里的语句反过来了}}
}
时间复杂度 O(m2m)O(m2^m)O(m2m)
这种方法又称为SOS DP:博客1 博客2
Code
[CF383E] Vowels
法一:SOS DP
正难则反,考虑统计不合法单词数
让每个单词对应一个状态AAA,第iii位表示第iii个字母是否在单词中出现(1为出现)
记元音字母集的补集为BBB
则不合法单词对应的AAA均为BBB的子集
设f[S]f[S]f[S]表示有多少个单词,其对应的AAA为SSS的子集,可以用sos dp求出:
for(int i=0;i<m;i++){for(int s=0;s<(1<<m);s++){if(s&(1<<i)){f[s]+=f[s^(1<<i)];//标准sos dp方程}}
}
答案即为(n−f[S])2(n-f[S])^2(n−f[S])2的异或和
Code
法二:SOS DP+容斥
设g[S]g[S]g[S]为元音集合为SSS时的合法单词数
设f[s]f[s]f[s]为有多少个单词,使sss为其代表的AAA的子集
即f[s]=∑i=1n[s∈wordi]f[s]=\sum_{i=1}^{n}[s\in word_i]f[s]=∑i=1n[s∈wordi]
g[S]=∑s∈S(−1)∣∣s∣∣+1f[s]g[S]=\sum_{s\in S}(-1)^{||s||+1}f[s]g[S]=∑s∈S(−1)∣∣s∣∣+1f[s]
但是这样做的时间复杂度是O(324)O(3^{24})O(324),会TLE,所以我们转换一下:
令f[s]=∑i=1n(−1)∣∣s∣∣+1[s∈wordi]f[s]=\sum_{i=1}^{n}(-1)^{||s||+1}[s\in word_i]f[s]=∑i=1n(−1)∣∣s∣∣+1[s∈wordi]
则g[S]=∑s∈Sf[s]g[S]=\sum_{s\in S}f[s]g[S]=∑s∈Sf[s]
求f[s]f[s]f[s]的复杂度是O(n⋅23)O(n\cdot 2^3)O(n⋅23)(对于每一个单词,枚举其子集)
求g[S]g[S]g[S]的复杂度是O(24⋅224)O(24\cdot 2^{24})O(24⋅224)(sos dp)
Code
[CF449D] Jzzhu and Numbers
法一:SOS DP+容斥
同COCI2011-2012 6
设 g[S]g[S]g[S] 为有多少种选数方案使SSS为选出数的按位与的子集
答案为∑S(−1)∣∣S∣∣g[S]\sum_{S}(-1)^{||S||}g[S]∑S(−1)∣∣S∣∣g[S]
设 f[S]f[S]f[S] 为有多少个箱子,使SSS为其代表的数A[i]A[i]A[i]的子集
g[S]=2f[S]−1g[S]=2^{f[S]}-1g[S]=2f[S]−1
Code
法二:FWT
设dp[i][s]dp[i][s]dp[i][s]为从前iii个数中选择,有多少种选数方案使选出数的按位与为sss
dp[i][j]=dp[i−1][j]+∑k&a[i]==jdp[i−1][k]dp[i][j]=dp[i-1][j]+\sum_{k\&a[i]==j}dp[i-1][k]dp[i][j]=dp[i−1][j]+∑k&a[i]==jdp[i−1][k]
dp[s&a[i]]+=dp[s]dp[s\&a[i]]+=dp[s]dp[s&a[i]]+=dp[s]
发现这个柿子本质上就是一个和卷积,可以用FWT解决
博客
[CF348D] Turtles
LGV引理
Code
[USACO20OPEN]Exercise G
循环了几次可以回到原地,当且仅当形成了一个环,假设每个环的长度是 aia_iai,那么k=lcmaik=\operatorname{lcm}a_ik=lcmai
又知道 lcmai\operatorname{lcm}a_ilcmai 其实就是将所有aia_iai分解质因数,然后取每个质数的最高次幂乘起来,
所以我们可以想到枚举素数来做dp
设 f[i][j]f[i][j]f[i][j] 表示前 iii 个素数总和为 jjj 的所有 KKK 的总和
枚举第 iii 个素数的幂进行转移:
f[i][j]=∑f[i−1][j−pik]×pikf[i][j]=\sum f[i-1][j-p_i^k]\times p_i^kf[i][j]=∑f[i−1][j−pik]×pik
可以滚动数组减掉一维
Code
双倍经验:[SCOI2009]游戏 博客
OSU!
设dp[i]dp[i]dp[i]表示到了第iii个位置的期望得分,
f[l]f[l]f[l]表示第iii个位置之前有长度为lll的连续1串的概率,
p[i]p[i]p[i]表示iii为1的概率,
则有转移:
dp[i]=dp[i−1]+p[i]∑lf[l]((l+1)3−l3)=dp[i−1]+p[i]∑lf[l](3l2+3l+1)dp[i]=dp[i-1]+p[i]\sum_lf[l]((l+1)^3-l^3)=dp[i-1]+p[i]\sum_l f[l](3l^2+3l+1)dp[i]=dp[i−1]+p[i]∑lf[l]((l+1)3−l3)=dp[i−1]+p[i]∑lf[l](3l2+3l+1)
于是考虑维护
El=∑lf[l]⋅lE_l=\sum_lf[l]\cdot lEl=∑lf[l]⋅l
El2=∑lf[l]⋅l2E_{l^2}=\sum_lf[l]\cdot l^2El2=∑lf[l]⋅l2
则总转移方程为:
El[i]=p[i]∑lf[l](l+1)=p[i](El[i−1]+∑lf[l])=p[i](El[i−1]+1)E_l[i]=p[i]\sum_lf[l](l+1)=p[i](E_l[i-1]+\sum_lf[l])=p[i](E_l[i-1]+1)El[i]=p[i]∑lf[l](l+1)=p[i](El[i−1]+∑lf[l])=p[i](El[i−1]+1)
El2[i]=p[i]∑lf[l](l2+2l+1)=p[i](El2[i−1]+2El[i−1]+1)E_{l^2}[i]=p[i]\sum_lf[l](l^2+2l+1)=p[i](E_{l^2}[i-1]+2E_{l}[i-1]+1)El2[i]=p[i]∑lf[l](l2+2l+1)=p[i](El2[i−1]+2El[i−1]+1)
dp[i]=dp[i−1]+p[i](3El2[i−1]+3El[i−1]+1)dp[i]=dp[i-1]+p[i](3E_{l^2}[i-1]+3E_l[i-1]+1)dp[i]=dp[i−1]+p[i](3El2[i−1]+3El[i−1]+1)
Code
收集邮票
设f[i]f[i]f[i]表示已经取到了iii种邮票,要取完剩余邮票的期望次数,
ans[i]ans[i]ans[i]表示已经取到了iii种邮票,要取完剩余邮票的期望价格
f[i]=inf[i]+n−inf[i+1]+1f[i]=\frac{i}{n}f[i]+\frac{n-i}{n}f[i+1]+1f[i]=nif[i]+nn−if[i+1]+1
⇒f[i]=f[i+1]+nn−i\Rightarrow f[i]=f[i+1]+\frac{n}{n-i}⇒f[i]=f[i+1]+n−in
ans[i]=in(ans[i]+f[i]+1)+n−in(ans[i+1]+f[i+1]+1)ans[i]=\frac{i}{n}(ans[i]+f[i]+1)+\frac{n-i}{n}(ans[i+1]+f[i+1]+1)ans[i]=ni(ans[i]+f[i]+1)+nn−i(ans[i+1]+f[i+1]+1)
⇒ans[i]=ans[i+1]+f[i+1]+in−if[i]+nn−i\Rightarrow ans[i]=ans[i+1]+f[i+1]+\frac{i}{n-i}f[i]+\frac{n}{n-i}⇒ans[i]=ans[i+1]+f[i+1]+n−iif[i]+n−in
注意:ans[i]≠(f[i]+1)f[i]2ans[i]\not=\frac{(f[i]+1)f[i]}{2}ans[i]=2(f[i]+1)f[i],理由如下:
ans[i]=∑cntpcnt(cnt+1)cnt2ans[i]=\sum_{cnt}p_{cnt}\frac{(cnt+1)cnt}{2}ans[i]=∑cntpcnt2(cnt+1)cnt
(f[i]+1)f[i]2=(∑cntpcntcnt+1)∑cntpcntcnt2\frac{(f[i]+1)f[i]}{2}=\frac{(\sum_{cnt}p_{cnt}cnt+1)\sum_{cnt}p_{cnt}cnt}{2}2(f[i]+1)f[i]=2(∑cntpcntcnt+1)∑cntpcntcnt
Code
[CF605E] Intergalaxy Trips
设f[i]f[i]f[i]为从iii走到nnn的期望耗时
考虑转移:
首先,我们一定不会找比当前点更劣的点转移,因为这还没有留在原地划算
其次,如果可以转移,那么转移到某点的唯一可能是比它优的点都转移不到
f[i]=1+f[i]∏j,fj<fi(1−pi,j)+∑j,fj<fif[j]pi,j∏k,pk<pj(1−pi,k)f[i]=1+f[i]\prod_{j,f_j<f_i}(1-p_{i,j})+\sum_{j,f_j<f_i}f[j]p_{i,j}\prod_{k,p_k<p_j}(1-p_{i,k})f[i]=1+f[i]∏j,fj<fi(1−pi,j)+∑j,fj<fif[j]pi,j∏k,pk<pj(1−pi,k)
⇒f[i]=1+∑j,fj<fif[j]pi,j∏k,pk<pj(1−pi,k)1−∏j,fj<fi(1−pi,j)\Rightarrow f[i]=\frac{1+\sum_{j,f_j<f_i}f[j]p_{i,j}\prod_{k,p_k<p_j}(1-p_{i,k})}{1-\prod_{j,f_j<f_i}(1-p_{i,j})}⇒f[i]=1−∏j,fj<fi(1−pi,j)1+∑j,fj<fif[j]pi,j∏k,pk<pj(1−pi,k)
实现:朴素版Dijkstra
博客
Code
常见优化与综合运用
[CF939F] Cutlet
设 dp[i][j]dp[i][j]dp[i][j] 表示前 rir_iri 分钟,把现在煎的面叫做正面,背面煎了 jjj 分钟的最小翻面次数
显然只会在一个区间至多翻 2 次:
不翻面,dp[i][j]=dp[i−1][j]dp[i][j]=dp[i-1][j]dp[i][j]=dp[i−1][j]
翻了一次,枚举正面煎了 kkk 秒,dp[i][j]=min(dp[i−1][r−j−k]+1)dp[i][j] = min(dp[i-1][r-j-k] + 1)dp[i][j]=min(dp[i−1][r−j−k]+1)
翻了两次,枚举背面煎了 kkk 秒,dp[i][j]=min(dp[i−1][j−k]+2)dp[i][j] = min(dp[i-1][j-k] + 2)dp[i][j]=min(dp[i−1][j−k]+2)
分别用单调队列维护即可
一句话解释单调队列优化dp:如果一个人比你年轻,还比你强,那你就永远打不过他了.jpg
Code
[CF311B] Cats Transport
因为对于任意一只猫,我们都可以直接算出如果有一个人要恰好接走它,需要在哪一时刻出发,我们设第i只猫对应的这个时刻为tit_{i}ti
对于第iii只猫,我们定义tit_{i}ti表示如果有人在tit_{i}ti时刻出发,此猫无须等待即可被接走
题目转化为:
现有ppp个人,要求为每个人指定一个出发时间aja_jaj,最小化∑i=1m(xi−ti)\sum_{i=1}^{m}(x_i-t_i)∑i=1m(xi−ti)(xi=Minaj≥ti{aj}x_i=Min_{a_j\geq t_i}\{a_j\}xi=Minaj≥ti{aj})
观察到每个人的出发时间aja_jaj必是tit_iti中的一个
那么假设第xxx个人的出发时间是tit_iti,第x−1x-1x−1个人的出发时间是tjt_jtj,
则第xxx个人会接走第j+1j+1j+1到第iii只猫
题目转化为:
现有ppp个人,要求为每个人选一只猫bjb_jbj,最小化∑j=1p∑i=bj−1+1bj(tbj−ti)\sum_{j=1}^{p}\sum_{i=b_{j-1}+1}^{b_j}(t_{b_j}-t_i)∑j=1p∑i=bj−1+1bj(tbj−ti)
设f[i][j]f[i][j]f[i][j]表示考虑到第iii个人,这个人选择了第jjj只猫的最小代价
记s[i]=∑k=1itks[i]=\sum_{k=1}^{i}t_ks[i]=∑k=1itk
则f[i][j]f[i][j]f[i][j]有转移式:
f[i][j]=Min{f[i−1][k]+tj(j−k)−(s[j]−s[k])}f[i][j]=Min\{f[i-1][k]+t_j(j-k)-(s[j]-s[k])\}f[i][j]=Min{f[i−1][k]+tj(j−k)−(s[j]−s[k])}
用斜率优化求f[i][j]f[i][j]f[i][j]:
f[i][j]=f[i−1][k]+tj(j−k)−(s[j]−s[k])f[i][j]=f[i-1][k]+t_j(j-k)-(s[j]-s[k])f[i][j]=f[i−1][k]+tj(j−k)−(s[j]−s[k])
⟺f[i−1][k]+s[k]=tj⋅k+f[i][j]+s[j]−tjj\iff f[i-1][k]+s[k]=t_j\cdot k+f[i][j]+s[j]-t_jj⟺f[i−1][k]+s[k]=tj⋅k+f[i][j]+s[j]−tjj
把f[i−1][k]+s[k]f[i-1][k]+s[k]f[i−1][k]+s[k]看成yyy,kkk看成xxx,tjt_jtj看成kkk,f[i][j]+s[j]−tjjf[i][j]+s[j]-t_jjf[i][j]+s[j]−tjj看成bbb
现要找到一个点P(k,f[i−1][k]+s[k])P(k,f[i-1][k]+s[k])P(k,f[i−1][k]+s[k])使得bbb最小
维护一个下凸壳,并在凸包上找最优决策点PPP即可
因为kkk单增,所以可以用单调队列实现
Code
[NOI2009] 诗人小G
设fif_ifi表示对前iii个句子排版后的最小不协调度
记si=∑j=1i(lenj+1)s_i=\sum_{j=1}^i(len_j+1)si=∑j=1i(lenj+1),则
fi=minj=0i−1{fj+∣si−sj−1−L∣P}f_i=min_{j=0}^{i-1}\{f_j+|s_i-s_j-1-L|^P\}fi=minj=0i−1{fj+∣si−sj−1−L∣P}
这条转移式是有决策单调性的
感性证明:
记hj(x)=∣x−sj−1−L∣Ph_j(x)=|x-s_j-1-L|^Phj(x)=∣x−sj−1−L∣P
不难看出hjh_jhj关于直线x=sj+1+Lx=s_j+1+Lx=sj+1+L对称
对于x>sj+1+Lx>s_j+1+Lx>sj+1+L的部分:
hj(x)=(x−sj−1−L)Ph_j(x)=(x-s_j-1-L)^Phj(x)=(x−sj−1−L)P
hj′(x)=P(x−sj−1−L)P−1h_j'(x)=P(x-s_j-1-L)^{P-1}hj′(x)=P(x−sj−1−L)P−1
所以hj′(x)h_j'(x)hj′(x)在(sj+1+L,+∞)(s_j+1+L,+\infin)(sj+1+L,+∞)上单增且恒大于0
对于x<sj+1+Lx<s_j+1+Lx<sj+1+L的部分:
根据对称性,hj′(x)h_j'(x)hj′(x)在(−∞,sj+1+L)(-\infin,s_j+1+L)(−∞,sj+1+L)上同样单增且恒小于0
又因为函数连续,所以hj′(x)h_j'(x)hj′(x)在R\RR上单增
又因为hj1(x)=hj(x+sj−sj1)h_{j_1}(x)=h_j(x+s_j-s_{j_1})hj1(x)=hj(x+sj−sj1),即不同的hj(x)h_j(x)hj(x)之间可以通过平移得到,
所以∀j1≠j2\forall j_1\not=j_2∀j1=j2,hj1(x)h_{j_1}(x)hj1(x)与hj2(x)h_{j_2}(x)hj2(x)最多一个交点
意会一下吧
所以 fff 的转移式满足决策单调性
%%%FlashHu大佬
严谨证明:
证明w(j,i)=∣si−sj−1−L∣Pw(j,i)=|s_i-s_j-1-L|^Pw(j,i)=∣si−sj−1−L∣P满足四边形不等式,本蒟蒻不会
贴个博客吧
Code
[CF868F] Yet Another Minimization Problem
设dpi,jdp_{i,j}dpi,j表示将序列的前iii个数划分成jjj段所需要的最小费用,
设wl,rw_{l,r}wl,r表示将lll到rrr划分成一段所需要的花费
显然有转移方程:dpi,j=min{dpx,j−1+wx+1,i}dp_{i,j} =min\{dp_{x,j-1}+w_{x+1,i}\}dpi,j=min{dpx,j−1+wx+1,i}
决策单调性证明:
法一(四边形不等式):
要证dpdpdp的转移具有决策单调性
即证∀a<b,w(a,b)+w(a+1,b+1)≤w(a,b+1)+w(a+1,b)\forall a<b,w(a,b)+w(a+1,b+1)\leq w(a,b+1)+w(a+1,b)∀a<b,w(a,b)+w(a+1,b+1)≤w(a,b+1)+w(a+1,b)
即证∀a<b,w(a,b)−w(a+1,b)≤w(a,b+1)−w(a+1,b+1)\forall a<b,w(a,b)-w(a+1,b)\leq w(a,b+1)-w(a+1,b+1)∀a<b,w(a,b)−w(a+1,b)≤w(a,b+1)−w(a+1,b+1)
即把区间从[a+1,b][a+1,b][a+1,b]拓到[a,b][a,b][a,b]的增量≤\leq≤把区间从[a+1,b+1][a+1,b+1][a+1,b+1]拓到[a,b+1][a,b+1][a,b+1]的增量
该式显然正确,因为在区间中增加一个元素,它对答案的贡献与区间内与它值相同的元素数量有关
法二:
记cx[i]c_x[i]cx[i]为区间[1,i][1,i][1,i]中值为jjj的元素个数
hj(i)=w(j+1,i)=∑x(cx[i]−cx[j])(cx[i]−cx[j]−1)2h_j(i)=w(j+1,i)=\sum_{x}\frac{(c_x[i]-c_x[j])(c_x[i]-c_x[j]-1)}{2}hj(i)=w(j+1,i)=∑x2(cx[i]−cx[j])(cx[i]−cx[j]−1)
因为(cx[i]−cx[j])(cx[i]−cx[j]−1)2\frac{(c_x[i]-c_x[j])(c_x[i]-c_x[j]-1)}{2}2(cx[i]−cx[j])(cx[i]−cx[j]−1)的导函数单增,所以合起来就可以得出hj′(i)h_j'(i)hj′(i)单增
结合图像可以证明dpdpdp的转移具有决策单调性
实现:
因为cost(j,i)cost(j,i)cost(j,i)不好快速计算,不适合用二分栈来做,所以这题是用分治实现的
Code
[SDOI2016]征途
高中数学告诉我们:s2=x2‾−x‾2s^2=\overline {x^2}-{\overline x}^2s2=x2−x2
所以m2s2=m∑vi2−(∑vi)2m^2s^2=m\sum v_i^2-(\sum v_i)^2m2s2=m∑vi2−(∑vi)2
−(∑vi)2-(\sum v_i)^2−(∑vi)2为定值,我们只要令∑vi2\sum v_i^2∑vi2最小即可
设f[i][j]f[i][j]f[i][j]表示把前iii段路分为jjj天走,∑k=1jvk2\sum_{k=1}^{j}v_k^2∑k=1jvk2的最小值
记sis_isi表示前iii段路的长度和
则f[i][j]f[i][j]f[i][j]有转移式:f[i][j]=min{f[x][j−1]+(si−sx)2}f[i][j]=min\{f[x][j-1]+(s_i-s_x)^2\}f[i][j]=min{f[x][j−1]+(si−sx)2}
斜率优化:
f[i][j]=f[x][j−1]+(si−sx)2f[i][j]=f[x][j-1]+(s_i-s_x)^2f[i][j]=f[x][j−1]+(si−sx)2
⟺2sisx+f[i][j]−si2=f[x][j−1]+sx2\iff 2s_is_x+f[i][j]-s_i^2=f[x][j-1]+s_x^2⟺2sisx+f[i][j]−si2=f[x][j−1]+sx2
把2si2s_i2si看成kkk,sxs_xsx看成xxx,f[i][j]−si2f[i][j]-s_i^2f[i][j]−si2看成bbb,f[x][j−1]+sx2f[x][j-1]+s_x^2f[x][j−1]+sx2看成yyy
找最优决策点即找到点(sx,f[x][j−1]+sx2)(s_x,f[x][j-1]+s_x^2)(sx,f[x][j−1]+sx2)使得bbb最小
Code
[HNOI2011]数学作业
容易得到递推式:f[n]=f[n−1]×10len(n)+nmodmf[n]=f[n-1]\times 10^{len(n)}+n \mod mf[n]=f[n−1]×10len(n)+nmodm
构造转移矩阵:
[f[n]n1]=[f[n−1]n−11]×[10len(n)00110111]\begin{bmatrix} f[n]&n&1\end{bmatrix}=\begin{bmatrix}f[n-1]&n-1&1\end{bmatrix}\times\begin{bmatrix}10^{len(n)}&0&0\\1&1&0\\1&1&1\end{bmatrix} [f[n]n1]=[f[n−1]n−11]×⎣⎡10len(n)11011001⎦⎤
如果不是10len(n)10^{len(n)}10len(n)这个奇怪的变量,这道题已经做完了
那我们干脆把10len(n)10^{len(n)}10len(n)变成常量:枚举位数,对每一个位数做一次矩阵快速幂
[USACO07NOV]Cow Relays G
经典结论:
用矩阵AAA表示有向图GGG的连通情况(Ai,j=1A_{i,j}=1Ai,j=1表示GGG中存在边i→ji\to ji→j)
那么从sss到ttt经过kkk条边的路径数=(Ak)s,t(A^k)_{s,t}(Ak)s,t
拓展到本题:
我们定义一种新运算∗*∗:
[a1,1a1,2⋯a1,ma2,1a2,2⋯a2,m⋮⋮⋱⋮an,1an,2⋯an,m]∗[b1,1b1,2⋯b1,nb2,1b2,2⋯b2,n⋮⋮⋱⋮bm,1bm,2⋯bm,n]=[c1,1c1,2⋯c1,nc2,1c2,2⋯c2,n⋮⋮⋱⋮cn,1cn,2⋯cn,n]\begin{bmatrix} a_{1,1}&a_{1,2}&\cdots&a_{1,m}\\a_{2,1}&a_{2,2}&\cdots&a_{2,m}\\\vdots&\vdots&\ddots&\vdots\\a_{n,1}&a_{n,2}&\cdots&a_{n,m}\end{bmatrix} * \begin{bmatrix} b_{1,1}&b_{1,2}&\cdots&b_{1,n}\\b_{2,1}&b_{2,2}&\cdots&b_{2,n}\\\vdots&\vdots&\ddots&\vdots\\b_{m,1}&b_{m,2}&\cdots&b_{m,n}\end{bmatrix} =\begin{bmatrix} c_{1,1}&c_{1,2}&\cdots&c_{1,n}\\c_{2,1}&c_{2,2}&\cdots&c_{2,n}\\\vdots&\vdots&\ddots&\vdots\\c_{n,1}&c_{n,2}&\cdots&c_{n,n}\end{bmatrix} ⎣⎡a1,1a2,1⋮an,1a1,2a2,2⋮an,2⋯⋯⋱⋯a1,ma2,m⋮an,m⎦⎤∗⎣⎡b1,1b2,1⋮bm,1b1,2b2,2⋮bm,2⋯⋯⋱⋯b1,nb2,n⋮bm,n⎦⎤=⎣⎡c1,1c2,1⋮cn,1c1,2c2,2⋮cn,2⋯⋯⋱⋯c1,nc2,n⋮cn,n⎦⎤
其中ci,j=Mink=1m{ai,k+bk,j}c_{i,j}=Min_{k=1}^m{}\{a_{i,k}+b_{k,j}\}ci,j=Mink=1m{ai,k+bk,j}
因为∗*∗运算满足结合律,所以A∗A∗A∗⋯∗AA*A*A*\cdots *AA∗A∗A∗⋯∗A仍然可以用快速幂求得
在这种新运算下,如果初始矩阵中Ai,jA_{i,j}Ai,j表示iii到jjj的最小距离
那么从sss到ttt经过kkk条边的最短路径长度=(Ak)s,t(A^k)_{s,t}(Ak)s,t(这里的AkA^kAk表示kkk个AAA相∗*∗)
博客
[SCOI2014]方伯伯的玉米田
首先本题需要确定一个事实:
每一次的拔高操作区间右端点一定是最右边的玉米
设f[i][j]f[i][j]f[i][j]表示以 iii 结尾,iii 这个点已经被 jjj 个拔高区间覆盖过,所能得到的最长不下降序列长度
f[i][j]=max{f[k][l]}+1(1≤k<i,0≤l≤j,h[i]+j≥h[l][k]f[i][j]=max\{f[k][l]\}+1(1\leqk<i,0\leq l\leq j,h[i]+j\geq h[l][k]f[i][j]=max{f[k][l]}+1(1≤k<i,0≤l≤j,h[i]+j≥h[l][k]
用数据结构优化转移即可
Code
[NOIP2018 提高组] 保卫王国
博客
Code