zoukankan      html  css  js  c++  java
  • 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
  • 相关阅读:
    细心也是一种态度
    EDM数据访问的三种方式
    如何快速提交网站备案 ICP备案
    c# winform 关于给静态全局变量赋值的问题
    c#DIY随机数类winform 2010
    手把手教你如何用IIS搭建手机WAP网站(图文)
    admin密码对应的MD5值,16位和32位,admin解密自己留着方便.
    C#实现MD5加密,winform c#2005
    最全的c#日期函数 winform
    如何解决因网站备案号没下来而网站被迫关闭的办法
  • 原文地址:https://www.cnblogs.com/ctyakwf/p/12489590.html
Copyright © 2011-2022 走看看