决策单调性
四边形不等式
二维
优化形如 \(f_{l,r}=\min\limits_{k=l}^{r-1} \{f_{l,k}+f_{k+1,r}+w_{l,r}\}\) 的 \(DP\) 方程,如石子合并问题。其直接做复杂度是 \(O(n^3)\) 的。
若 \(w\) 满足:
四边形不等式(交叉小于包含):对于任意 \(a \leqslant b \leqslant c \leqslant d\),满足 \(w_{a,c}+w_{b,d} \leqslant w_{b,c}+w_{a,d}\)。(当等号永远成立时,称其满足四边形恒等式)
区间包含单调性:对于任意 \(a \leqslant b \leqslant c \leqslant d\),满足 \(w_{b,c} \leqslant w_{a,d}\)。
则 \(f\) 也满足四边形不等式,那么决策点 \(s\) 满足 \(s_{l,r-1} \leqslant s_{l,r} \leqslant s_{l+1,r}\),得:
复杂度就降为 \(O(n^2)\) 了。
当 \(w\) 满足 \(w_{l,r}+w_{l+1,r+1} \leqslant w_{l+1,r}+w_{l,r+1}\) 时,可以推得其满足四边形不等式。
一维
优化形如 \(f_i=\min\limits_{j=1}^{i-1} \{f_j+w_{j,i}\}\) 的 \(DP\) 方程。
\(w\) 不用满足区间包含单调性,只需满足四边形不等式,\(f\) 就满足决策单调性。
证明
当 \(w\) 满足 \(w_{l,r}+w_{l+1,r+1} \leqslant w_{l+1,r}+w_{l,r+1}\) 时,可以推得其满足四边形不等式。
若 \(w_1,w_2\) 满足四边形不等式或区间包含单调性,则对于任意 \(c_1,c_2 \geqslant 0\),\(c_1w_1+c_2w_2\) 也满足四边形不等式或区间包含单调性。
若 \(w\) 可以通过函数 \(f(x),g(x)\) 表示,即 \(w_{l,r}=f(r)-g(l)\),则 \(w\) 满足四边形恒等式。当 \(f,g\) 单调递增时, \(w\) 还满足区间包含单调性。
若 \(w_{l,r}\) 满足四边形不等式和区间包含单调性,则对于的下凸函数 \(f(x)\),得 \(f(w_{l,r})\) 满足四边形不等式。
若 \(w_{l,r}\) 满足四边形不等式和区间包含单调性,则对于单调递增的下凸函数 \(f(x)\),得 \(f(w_{l,r})\) 满足四边形不等式和区间包含单调性。
决策单调性
决策单调性:状态转移的最优决策点单调递增。若四边形不等式是的不等号是相反的,则单调性也会相反,若是去最大值,单调性也会相反。
可以用二分栈或者分治来实现,二分栈比分治会更快,复杂度都为 \(O(n \log n)\)。
二分栈
要求必须快速 \(O(1)\) 计算 \(w_{i,j}\)。
二分栈中存有三元组 \((l,r,pos)\),\(l\) 代表决策的作用起点,\(r\) 代表决策的作用终点,\(pos\) 是决策点的位置。
若当前状态\(i\)已经不在栈头决策点的范围内,就弹出栈头。若位置为\(i\)的决策优于栈尾的决策,才进行下一步操作,来更新决策。若新决策点的作用范围覆盖了旧决策点,就弹出栈尾。若栈空了,就直接加入新决策点,说明其当前是最优的,否则就通过在旧决策点的范围内二分,来确定旧决策点的终点和新决策的的起点。
Lightning Conductor:\(f_i=\max\limits_{j=1}^{i-1}\{a_j-a_i+\sqrt{|i-j|}\}\)
double calc(int i,int j)
{
return a[j]-a[i]+sqrt(i-j);
}
int find(node t,int x)
{
int l=t.l,r=t.r,ans=t.r+1;
while(l<=r)
{
int mid=(l+r)>>1;
if(calc(mid,x)>=calc(mid,t.pos)) r=mid-1,ans=mid;
else l=mid+1;
}
return ans;
}
void dp(double *f)
{
q[h=t=1]=node(1,n,0);
for(int i=1;i<=n;++i)
{
while(h<=t&&q[h].r<i) h++;
f[i]=calc(i,q[h].pos);
if(calc(n,i)>=calc(n,q[t].pos))
{
while(h<=t&&calc(q[t].l,i)>=calc(q[t].l,q[t].pos)) t--;
if(h>t) q[++t]=node(i,n,i);
else
{
int x=find(q[t],i);
q[t].r=x-1,q[++t]=node(x,n,i);
}
}
}
}
分治
对于区间 \([l,r]\),已知其最优决策范围为 \([L,R]\)。取 \(mid\) 后扫一遍区间 \([L,\min(mid,R)]\) 来得出 \(mid\) 的 \(f\) 值和最优决策点 \(pos\),那么左区间的最优决策范围为 \([L,pos]\),右区间的最优决策范围为 \([pos,R]\)。
应用分治时要求保证区间 \([L,l-1]\) 的信息都已存在,因此应用分治大部分时候都是分层的两维 \(DP\)。
Lightning Conductor:\(f_i=\max\limits_{j=1}^{i-1}\{a_j-a_i+\sqrt{|i-j|}\}\)
double calc(int i,int j)
{
return a[j]-a[i]+sqrt(i-j);
}
void solve(int l,int r,int L,int R,double *f)
{
if(l>r) return;
int pos,mid=(l+r)>>1;
for(int i=L;i<=min(mid,R);++i)
{
double v=calc(mid,i);
if(v>f[mid]) f[mid]=v,pos=i;
}
solve(l,mid-1,L,pos,f),solve(mid+1,r,pos,R,f);
}
可以处理无法快速 \(O(1)\) 计算 \(w_{i,j}\) 的 \(DP\)。
Yet Another Minimization Problem:\(f_{i,j}=\min\limits_{k=1}^{i}\{f_{k,j-1}+w_{k,i}\}\),其中 \(w_{l,r}\) 为区间 \([l,r]\) 相同元素的对数。
void add(int c)
{
sum+=cnt[c],cnt[c]++;
}
void del(int c)
{
sum-=cnt[c]-1,cnt[c]--;
}
ll get(int ql,int qr)
{
while(l<ql) del(a[l++]);
while(r>qr) del(a[r--]);
while(l>ql) add(a[--l]);
while(r<qr) add(a[++r]);
return sum;
}
void solve(int id,int l,int r,int L,int R)
{
if(l>r) return;
int pos,mid=(l+r)>>1;
for(int i=L;i<=min(mid,R);++i)
{
ll v=f[i][id-1]+get(i+1,mid);
if(v<f[mid][id]) f[mid][id]=v,pos=i;
}
solve(id,l,mid-1,L,pos),solve(id,mid+1,r,pos,R);
}
指针的移动均摊是 \(O(1)\) 的。