zoukankan      html  css  js  c++  java
  • [CF1304F] Animal Observation

    (f[i][j]) 为第 (i) 天在第 (j) 个位置放置的最大值,设 (s[i][j]) 是第 (i) 行的前缀和,则

    [egin{align} f[i][j] & =s[i+1][j+k-1]-s[i+1][j-1]+ \ max_l & egin{cases} f[i-1][l]+s[i][j+k-1]-s[i][j-1] & (1 leq l leq j-k) \ f[i-1][l]+s[i][j+k-1]-s[i][l+k-1] & (j-k+1 leq l leq j) \ f[i-1][l]+s[i][l-1]-s[i][j-1] & (j+1 leq l leq j+k-1) \ f[i-1][l]+s[i][j+k-1]-s[i][j-1] & (j+k leq l leq m-k+1) end{cases} end{align} ]

    如果暴力转移,则复杂度 (O(nm^2 ))

    如果 (k) 很小,那么对中间两种情况暴力转移,旁边两种由于只有 (f[i-1][l])(l) 有关,可以预处理前后缀 (max) 来解决,复杂度 (O(nmk))

    (k) 变大时,两侧的情况仍然暴力转移,中间的情况可以暴力用以 (l) 为下标的单调队列维护 (f[i-1][l]-s[i][l+k-1])(f[i-1][l]+s[i][l-1])

    (如果想偷懒也可以敲个线段树维护一下)

    (发现单调队列优化DP不太熟练,准备要复习下)

    #include <bits/stdc++.h>
    using namespace std;
    
    #define int long long
    const int N = 55, M = 20005;
    
    int a[N][M],s[N][M],f[N][M],n,m,k,q[M],qt[M],l,r;
    
    signed main() {
        cin>>n>>m>>k;
        for(int i=1;i<=n;i++) {
            for(int j=1;j<=m;j++) {
                cin>>a[i][j];
                s[i][j]=s[i][j-1]+a[i][j];
            }
        }
        for(int i=1;i<=m-k+1;i++)
            f[1][i]=s[1][i+k-1]-s[1][i-1]+s[2][i+k-1]-s[2][i-1];
        for(int i=2;i<=n;i++) {
            for(int j=1;j<=m-k+1;j++)
                q[j]=f[i-1][j];
            for(int j=1;j<=m-k+1;j++)
                q[j]=max(q[j],q[j-1]);
            for(int j=k;j<=m-k+1;j++)
                f[i][j]=max(f[i][j],q[j-k]+s[i][j+k-1]-s[i][j-1]);
            for(int j=m-k+1;j;j--)
                q[j]=f[i-1][j];
            for(int j=m-k+1;j;j--)
                q[j]=max(q[j],q[j+1]);
            for(int j=1;j<=m-k+1;j++)
                f[i][j]=max(f[i][j],q[j+k]+s[i][j+k-1]-s[i][j-1]);
            l=1;r=0;
            for(int j=1;j<=m-k+1;j++) q[j]=-1e9;
            for(int j=1;j<=m-k+1;j++) {
                while(l<=r && q[r]<f[i-1][j]-s[i][j+k-1]) --r;
                ++r;
                q[r]=f[i-1][j]-s[i][j+k-1];
                qt[r]=j;
                while(l<=r && qt[l]<j-k+1) ++l;
                if(l<=r) f[i][j]=max(f[i][j],q[l]+s[i][j+k-1]);
            }
            l=1;r=0;
            for(int j=1;j<=m-k+1;j++) q[j]=-1e9;
            for(int j=m-k+1;j;--j) {
                while(l<=r && q[r]<f[i-1][j]+s[i][j-1]) --r;
                ++r;
                q[r]=f[i-1][j]+s[i][j-1];
                qt[r]=j;
                while(l<=r && qt[l]>j+k-1) ++l;
                if(l<=r) f[i][j]=max(f[i][j],q[l]-s[i][j-1]);
            }
            for(int j=1;j<=m-k+1;j++) f[i][j]+=s[i+1][j+k-1]-s[i+1][j-1];
        }
        int ans=0;
        /*for(int i=1;i<=n;i++) {
            for(int j=1;j<=m;j++) cout<<f[i][j]<<"	";
            cout<<endl;
        }*/
        for(int i=1;i<=m;i++) ans=max(f[n][i],ans);
        cout<<ans;
    }
    
    
  • 相关阅读:
    app版本升级的测试点
    APP测试完整测试用例设计方法
    多条件组合查询---测试用例设计
    上传文件和导出的测试用例设计
    需求评审时,测试应该做什么?
    什么是PRD?
    什么是测试计划?
    由谁来编写测试计划?
    测试计划模板
    无法预览图片
  • 原文地址:https://www.cnblogs.com/mollnn/p/12330798.html
Copyright © 2011-2022 走看看