luogu P2219 [HAOI2007] green belt construction

Rectangular $ C \ times D $ rectangular $ A \ times B $ among (no common edge), the contribution is defined as a rectangle $ A \ times B $ rectangular $ C \ times D $ elements and the difference between the maximum contribution to seek .

Consider monotonous queue. Twice dp, to find the $ (i, j) $ is the smallest of the small rectangular elements and large rectangle included in the lower right corner.

// luogu-judger-enable-o2
#include<iostream>
#include<cstdio>
#include<cstring>
#include<algorithm>
#define mid (l+r)/2
#define N 100005
#define log 40
#define lowbit(x) x&-x
#define mod 998244353
using namespace std;
inline int read()
{
    int x=0,f=1;
    char ch=getchar();
    while(ch<'0'||ch>'9'){if(ch=='-')f=-1;ch=getchar();}
    while(ch>='0'&&ch<='9'){x=x*10+ch-'0';ch=getchar();}
    return x*f;
}
int sum1[1005][1005],sum2[1005][1005],sum[1005][1005];
int num[1005][1005];
int q1[1005][1005],q2[1005][1005];
int q[10005];
int l,r;
int n,m,a,b,c,d;
int main()
{
    scanf("%d%d",&n,&m);
    scanf("%d%d%d%d",&a,&b,&c,&d);
    int i,j,k;
    for(i=1;i<=n;i++)
        for(j=1;j<=m;j++)
            scanf("%d",&num[i][j]);
    for(i=1;i<=n;i++)
        for(j=1;j<=m;j++)
            sum[i][j]=sum[i][j-1]+sum[i-1][j]-sum[i-1][j-1]+num[i][j];
    for(i=a;i<=n;i++)
        for(j=b;j<=m;j++)
            sum1[i][j]=sum[i][j]-sum[i][j-b]+sum[i-a][j-b]-sum[i-a][j];
    for(i=c+1;i<n;i++)
        for(j=d+1;j<m;j++)
            sum2[i][j]=sum[i][j]-sum[i][j-d]+sum[i-c][j-d]-sum[i-c][j];
    for(i=c+1;i<n;i++)
    {
        l=1;
        r=0;
        for(j=d+1;j<m;j++)
        {
            while(l<=r&&q[l]<j-b+2+d)
                l++;
            while(l<=r&&sum2[i][q[r]]>=sum2[i][j])
                r--;
            q[++r]=j;
            if(j>=b-1)
                q1[i][j+1]=sum2[i][q[l]];
        }
    }
    for(j=b;j<=m;j++)
    {
        l=1;
        r=0;
        for(i=c+1;i<n;i++)
        {
            while(l<=r&&q[l]<i-a+2+c)
                l++;
            while(l<=r&&q1[q[r]][j]>=q1[i][j])
                r--;
            q[++r]=i;
            if(i>=a-1)
                q2[i+1][j]=q1[q[l]][j];
        }
    }
    int ans=0;
    for(i=a;i<=n;i++)
        for(j=b;j<=m;j++)
            ans=max(ans,sum1[i][j]-q2[i][j]);
    cout<<ans;
    return 0;
}

 

Guess you like

Origin www.cnblogs.com/handsome-wjc/p/11264500.html