zoukankan      html  css  js  c++  java
  • 动态规划训练之十九

    分析:

    考虑初级的dpO(N3)

    code:

        for(ri K=1;K<=n;K++)
    	for(ri i=1;i<=n;i++){
    	for(ri j=i-1;j>=1;j--)
    	if(sum[i]-sum[j]<=w)
    	dp[i][K]=min(dp[j][K-1]+K*(sum[i]-sum[j])+querymax(j+1,i)-querymin(j+1,i),dp[i][K]);
    

    考虑能不能降维
    发现这个K很多事

    想到把K这一维删去

    这里就要用到费用提前算的思想了

    补充:费用提前算

    https://www.luogu.org/problem/P2365

    分析:

    考虑最原始的dp:

    f[i,j]=min{f[k,j-1]+(s×j+sumT[i])×(sumF[i]-sumF[k])}(0<=k<i)

    复杂度N3

    把费用提前算:将以后会算上的,先加上,除掉后效性

    f[i]=min{f[k]+sumT[i]×(sumF[i]-sumF[k])+s*(sumF[n]-sumF[k])}

    这题数据也就N2,其实这题还可以斜率优化,当然懒得说了

    回到正题

    dp[i,K]=min(dp[j,K-1]+K*(sum[i]-sum[j])+querymax(j+1,i)-querymin(j+1,i),dp[i,K])

    经过变换:

    dp[i]=min{dp[j]+(sum[i]-sum[j])+querymax(j+1,i)-querymin(j+1,i)+sum[n]-sum[i]};

    后面的相比前面的系数差1

    这样是N2的,还是不行怎么办

    发现还可以单调队列优化

    code by std:

    #include<bits/stdc++.h>
    #define ll long long
    using namespace std;
    const int maxn=1e5+10;
    int t,n,wi,q[maxn];
    ll sum[maxn],stmn[maxn][30],stmx[maxn][30],f[maxn];
    inline void stwk(){
        for(int i=1;i<=t;i++) for(int j=1;j+(1<<(i-1))<=n;j++){
            stmn[j][i]=min(stmn[j][i-1],stmn[j+(1<<(i-1))][i-1]);
            stmx[j][i]=max(stmx[j][i-1],stmx[j+(1<<(i-1))][i-1]);
        }
    }
    inline ll ask(int l,int r){
        int k=log2(r-l+1);
        ll minn=min(stmn[l][k],stmn[r-(1<<k)+1][k]),maxx=max(stmx[l][k],stmx[r-(1<<k)+1][k]);
        return maxx-minn;
    }
    int main()
    {
        scanf("%d%d",&n,&wi);
        t=log2(n)+1;
        for(int x,i=1;i<=n;i++){
            scanf("%d",&x);
            sum[i]=(ll)sum[i-1]+x;stmn[i][0]=(ll)x;stmx[i][0]=(ll)x;
        }
        stwk();
        memset(f,0x3f,sizeof(f));
        f[0]=0;int l=0,r=0;
        for(int i=1;i<=n;i++){
            while(l<=r && sum[i]-sum[q[l]]>wi) l++;
            for(int j=l;j<=r;j++) f[i]=min(f[i],f[q[j]]+sum[n]-sum[q[j]]+ask(q[j]+1,i));
            while(l<=r && f[i]<=f[q[r]]) r--;
            q[++r]=i;
        }
        printf("%lld
    ",f[n]);
        return 0;
    }
    

    开始我有疑问,为什么已经是单调队列优化dp了,中间还要枚举?

    后来幡然醒悟,因为价值还有最大值-最小值啊

    至于复杂度,应该不高吧

  • 相关阅读:
    1.8 接口中的静态方法
    1.7 默认方法
    1.6 变量作用域
    汉字转拼音
    1.5 构造器引用
    1.4 方法引用
    循环中冲不掉外部定义的变量
    getBoundingClientRect
    Angular1.0 在Directive中调用Controller的方法
    horizontalDragMaxWidth:0;就没有水平滚动条了
  • 原文地址:https://www.cnblogs.com/wzxbeliever/p/11791051.html
Copyright © 2011-2022 走看看