决策单调性

1|0四边形不等式

1|1二维

优化形如 fl,r=mink=lr1{fl,k+fk+1,r+wl,r}DP 方程,如石子合并问题。其直接做复杂度是 O(n3) 的。

w 满足:

四边形不等式(交叉小于包含):对于任意 abcd,满足 wa,c+wb,dwb,c+wa,d。(当等号永远成立时,称其满足四边形恒等式)

区间包含单调性:对于任意 abcd,满足 wb,cwa,d

f 也满足四边形不等式,那么决策点 s 满足 sl,r1sl,rsl+1,r,得:

1l<rnsl+1,rsl,r1=i=1nsi,ns1,in2

复杂度就降为 O(n2) 了。

w 满足 wl,r+wl+1,r+1wl+1,r+wl,r+1 时,可以推得其满足四边形不等式。

1|2一维

优化形如 fi=minj=1i1{fj+wj,i}DP 方程。

w 不用满足区间包含单调性,只需满足四边形不等式,f 就满足决策单调性。

1|3证明

w 满足 wl,r+wl+1,r+1wl+1,r+wl,r+1 时,可以推得其满足四边形不等式。

w1,w2 满足四边形不等式或区间包含单调性,则对于任意 c1,c20c1w1+c2w2 也满足四边形不等式或区间包含单调性。

w 可以通过函数 f(x),g(x) 表示,即 wl,r=f(r)g(l),则 w 满足四边形恒等式。当 f,g 单调递增时, w 还满足区间包含单调性。

wl,r 满足四边形不等式和区间包含单调性,则对于的下凸函数 f(x),得 f(wl,r) 满足四边形不等式。

wl,r 满足四边形不等式和区间包含单调性,则对于单调递增的下凸函数 f(x),得 f(wl,r) 满足四边形不等式和区间包含单调性。

2|0决策单调性

决策单调性:状态转移的最优决策点单调递增。若四边形不等式是的不等号是相反的,则单调性也会相反,若是去最大值,单调性也会相反。

可以用二分栈或者分治来实现,二分栈比分治会更快,复杂度都为 O(nlogn)

2|1二分栈

要求必须快速 O(1) 计算 wi,j

二分栈中存有三元组 (l,r,pos)l 代表决策的作用起点,r 代表决策的作用终点,pos 是决策点的位置。

若当前状态i已经不在栈头决策点的范围内,就弹出栈头。若位置为i的决策优于栈尾的决策,才进行下一步操作,来更新决策。若新决策点的作用范围覆盖了旧决策点,就弹出栈尾。若栈空了,就直接加入新决策点,说明其当前是最优的,否则就通过在旧决策点的范围内二分,来确定旧决策点的终点和新决策的的起点。

Lightning Conductorfi=maxj=1i1{ajai+|ij|}

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); } } } }

2|2分治

对于区间 [l,r],已知其最优决策范围为 [L,R]。取 mid 后扫一遍区间 [L,min(mid,R)] 来得出 midf 值和最优决策点 pos,那么左区间的最优决策范围为 [L,pos],右区间的最优决策范围为 [pos,R]

应用分治时要求保证区间 [L,l1] 的信息都已存在,因此应用分治大部分时候都是分层的两维 DP

Lightning Conductorfi=maxj=1i1{ajai+|ij|}

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) 计算 wi,jDP

Yet Another Minimization Problemfi,j=mink=1i{fk,j1+wk,i},其中 wl,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) 的。


__EOF__

本文作者lhm_
本文链接https://www.cnblogs.com/lhm-/p/12229791.html
关于博主:sjzez 的一名 OI 学生
版权声明:转载标明出处
声援博主:希望得到宝贵的建议
posted @   lhm_liu  阅读(726)  评论(0编辑  收藏  举报
编辑推荐:
· SQL Server 2025 AI相关能力初探
· Linux系列:如何用 C#调用 C方法造成内存泄露
· AI与.NET技术实操系列(二):开始使用ML.NET
· 记一次.NET内存居高不下排查解决与启示
· 探究高空视频全景AR技术的实现原理
阅读排行:
· 阿里最新开源QwQ-32B,效果媲美deepseek-r1满血版,部署成本又又又降低了!
· 单线程的Redis速度为什么快?
· SQL Server 2025 AI相关能力初探
· AI编程工具终极对决:字节Trae VS Cursor,谁才是开发者新宠?
· 展开说说关于C#中ORM框架的用法!
点击右上角即可分享
微信分享提示