决策单调性
Posted lhm-
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了决策单调性相关的知识,希望对你有一定的参考价值。
决策单调性:状态转移的最优决策点单调递增
可以用二分栈或者分治来实现
二分栈中存有三元组((l,r,pos)),(l)代表决策的作用起点,(r)代表决策的作用终点,(pos)是决策点的位置
若当前状态(i)已经不在栈头决策点的范围内,就弹出栈头
若位置为(i)的决策优于栈尾的决策,才进行下一步操作,来更新决策
若新决策点的作用范围覆盖了旧决策点,就弹出栈尾
若栈空了,就直接加入新决策点,说明其当前是最优的,否则就通过在旧决策点的范围内二分,来确定旧决策点的终点和新决策的的起点
时间复杂度(O(n log n))
诗人小G:(f_i=minlimits_{j=0}^{i-1} f_j+|s_i-s_j-L-1|^P)
(code:)
ld calc(int i,int j)
{
return f[j]+qp((ld)abs(s[i]-s[j]-l-1),p);
}
int find(node t,int x)
{
int l=t.l,r=t.r,pos=t.pos;
while(l<=r)
{
int mid=(l+r)>>1;
if(calc(mid,x)<=calc(mid,pos)) r=mid-1;
else l=mid+1;
}
return l;
}
......
q[h=t=1]=(node){1,n,0};
for(int i=1;i<=n;++i)
{
if(h<=t&&q[h].r<i) h++;
f[i]=calc(i,q[h].pos),pre[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};
}
}
}
Lightning Conductor:(f_i=maxlimits_{j=1}^{i-1} a_j-a_i+sqrt{|i-j|})
二分栈写法
(code:)
struct node
{
int l,r,pos;
}q[maxn];
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,pos=t.pos;
while(l<=r)
{
int mid=(l+r)>>1;
if(calc(mid,x)>=calc(mid,pos)) r=mid-1;
else l=mid+1;
}
return l;
}
void dp(double *f)
{
q[h=t=1]=(node){1,n,0};
for(int i=1;i<=n;++i)
{
if(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};
}
}
}
}
分治写法
(code:)
ld calc(int i,int j)
{
return (ld)a[j]+(ld)sqrt((ld)(i-j));
}
void solve(int l,int r,int L,int R,ld *f)
{
int x=0,mid=(l+r)>>1;
for(int i=L;i<=min(mid,R);++i)
{
ld now=calc(mid,i);
if(now>f[mid]) f[mid]=now,x=i;
}
f[mid]-=a[mid];
if(l<mid) solve(l,mid-1,L,x,f);
if(r>mid) solve(mid+1,r,x,R,f);
}
以上是关于决策单调性的主要内容,如果未能解决你的问题,请参考以下文章
bzoj 2216 [Poi2011]Lightning Conductor 决策单调性+dp