hdu 3855(单调栈优化DP+思路+好题)

单调栈可以维护一个长度递增的序列,当新加入的元素不递增时,会把前面的元素截断,使其保持递增

由于截断之后大量的元素长度相同,所以没有必要把所有所有元素压入栈,只需将这些元素压缩成一个(用矩阵块和表示!),记录个数,放入栈既可。

//#pragma comment(linker, "/STACK:102400000")
#include<cstdlib>
#include<iostream>
#include<cstdio>
#include<cmath>
#include<cstring>
#include<algorithm>
#include<set>
#include<map>
#include<list>
#include<queue>
#include<vector>
#define tree int o,int l,int r
#define lson o<<1,l,mid
#define rson o<<1|1,mid+1,r
#define lo o<<1
#define ro o<<1|1
#define ULL unsigned long long
#define LL long long
#define inf 0x7fffffff
#define eps 1e-7
#define N 3009
using namespace std;
int m,n,T,t,x,y,k;
LL a[N][N],sum[N][N];
LL q[N],top,len[N],d[N];
LL sumhe(int x,int y,int a,int b)
{
    return sum[x][y]-sum[a][y]-sum[x][b]+sum[a][b];
}
int main()
{
#ifndef ONLINE_JUDGE
    freopen("ex.in","r",stdin);
#endif
    scanf("%d",&T);
    while(T--)
    {
        scanf("%d%d%d",&n,&m,&k);
        for(int i=1; i<=n; i++)
            for(int j=1; j<=m; ++j)
            {
                scanf("%I64d",&a[i][j]);
                sum[i][j]=sum[i-1][j]+sum[i][j-1]-sum[i-1][j-1]+a[i][j];
            }
        memset(len,0,sizeof(len));
        LL ans=0;
        for(int i=1; i<=n; i++)
        {
            top=0;
            d[0]=0;
            q[top++]=0;
            for(int j=1; j<=m; ++j)
            {
                if(a[i][j]>=k)len[j]++;
                else len[j]=0;
                while(top>0&&len[j]<len[q[top-1]])
                    top--;
                int pre=q[top-1];

                if(len[j]==0)
                    d[j]=0;
                else
                    d[j]=d[pre]+sumhe(i,j,i-len[j],pre);
                ans=max(ans,d[j]);
                q[top++]=j;
            }
        }
        printf("%I64d
",ans);
    }
    return 0;
}

  

原文地址:https://www.cnblogs.com/sbaof/p/3329998.html