决策单调性

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

以上是关于决策单调性的主要内容,如果未能解决你的问题,请参考以下文章

决策单调性

决策单调性优化dp

决策单调性优化dp 专题练习

bzoj 2216 [Poi2011]Lightning Conductor 决策单调性+dp

luogu P6087 [JSOI2015]送礼物 二分 单调队列 决策单调性

单调性优化学习笔记