• POJ3926 Parade (单调队列dp)


    这道题是典型的单调队列优化问题,题目虽然说得是交叉点,但是其实你可以把他看成格子,这也是常见技巧

    之后你发现这就是求一个前缀和与前一行的值的相互关系,然后求最大值。大于指定长度的删掉

    但是本题要注意的要求两遍,因为他可以往左也可以往右,并且注意不要忘记可以用0点更新。

    此外,读入很严格,需要读入优化,以后做题感觉复杂度没错可以试试改变读入的方法

    #include<iostream>
    #include<queue>
    #include<map>
    #include<vector>
    #include<cstdio>
    #include<algorithm>
    #include<stack>
    #include<cstring>
    using namespace std;
    typedef long long ll;
    const int N=5e5+10;
    const int inf=0x3f3f3f3f;
    inline int read(){
        int x = 0, f = 1; char c = getchar();
        while(c < '0' || c > '9') { if(c == '-') f = -1; c = getchar(); }
        while(c >= '0' && c <= '9') { x = x * 10 + c - '0'; c = getchar(); }
        return x * f;
    }
    int v[110][11000];
    int len[110][11000];
    int f[110][11000];
    int q[N];
    int main(){
        int i;
        int n,m,k;
        int j;
        while(scanf("%d%d%d",&n,&m,&k)){
            if(n==0&&m==0&&k==0)
                break;
            n++;
            for(i=1;i<=n;i++){
                for(j=1;j<=m;j++){
                    v[i][j]=read();
                    v[i][j]+=v[i][j-1];
                }
            }
            memset(f,0,sizeof f);
            for(i=1;i<=n;i++){
                for(j=1;j<=m;j++){
                    len[i][j]=read();
                    len[i][j]+=len[i][j-1];
                }
            }
            for(i=1;i<=n;i++){
                int hh=0;
                int tt=0;
                q[0]=0;
                for(j=1;j<=m;j++){
                    while(hh<=tt&&f[i-1][j]-v[i][j]>f[i-1][q[tt]]-v[i][q[tt]])
                        tt--;
                    q[++tt]=j;
                    while(hh<=tt&&len[i][j]-len[i][q[hh]]>k)
                        hh++;
                    f[i][j]=f[i-1][q[hh]]+v[i][j]-v[i][q[hh]];
                }
                hh=0;
                tt=0;
                q[0]=m;
                for(j=m;j>=0;j--){
                    while(hh<=tt&&f[i-1][j]+v[i][j]>f[i-1][q[tt]]+v[i][q[tt]])
                        tt--;
                    q[++tt]=j;
                    while(hh<=tt&&len[i][q[hh]]-len[i][j]>k)
                        hh++;
                    f[i][j]=max(f[i][j],f[i-1][q[hh]]+v[i][q[hh]]-v[i][j]);
                }
            }
            int res=-0x3f3f3f3f;
            for(i=1;i<=m;i++){
                res=max(f[n][i],res);
            }
            printf("%d
    ",res);
        }
        return 0;
    }
    View Code
  • 相关阅读:
    [CF703D] Mishka and Interesting sum
    [CF1454F] Array Partition
    [CF13E] Holes
    [CF1110D] Jongmah
    [CF1204D2] Kirk and a Binary String
    [CF936B] Sleepy Game
    [CF546E] Soldier and Traveling
    [CF1025D] Recovering BST
    [CF598C] Nearest vectors
    [CF988E] Divisibility by 25
  • 原文地址:https://www.cnblogs.com/ctyakwf/p/12489590.html
Copyright © 2020-2023  润新知