我是题面

这道题跟理想的正方形很像,不大明白蛤OI是怎么想的,一年出两道这么相近的题

这道题有两个矩形,所以就有了两种做法(说是两种做法,其实只是维护的矩形不同)

一种是维护大矩形,一种是维护小矩形,我这里采取了维护小矩形的方法

先求出以\((i,j)\)为左上角的大矩形和小矩形的权值和为多少,然后用单调队列维护以(i,j)为左上角的大矩形里能放得最小的小矩形是哪个,最后做差得答案即可

下面是代码

#include<algorithm>
#include<iostream>
#include<cstring>
#include<cstdio>
#include<cctype>
#define ll long long
#define gc getchar
#define maxn 1005
using namespace std;

inline ll read(){
    ll a=0;int f=0;char p=gc();
    while(!isdigit(p)){f|=p=='-';p=gc();}
    while(isdigit(p)){a=(a<<3)+(a<<1)+(p^48);p=gc();}
    return f?-a:a;
}int n,m,a,b,c,d,ans,w[maxn][maxn];
int w1[maxn][maxn],w2[maxn][maxn],x[maxn][maxn],y[maxn][maxn];

struct ahaha{
    int s,id;
}q[maxn];int h,t;

int main(){
    n=read();m=read();a=read();b=read();c=read();d=read();
    for(int i=1;i<=n;++i)
        for(int j=1;j<=m;++j)
            w[i][j]=w[i-1][j]+w[i][j-1]+read()-w[i-1][j-1];
    for(int i=1;i<=n-c+1;++i)
        for(int j=1;j<=m-d+1;++j){
            w1[i][j]=w[i+c-1][j+d-1]-w[i+c-1][j-1]-w[i-1][j+d-1]+w[i-1][j-1];
            if(i<=n-a+1&&j<=m-b+1)
                w2[i][j]=w[i+a-1][j+b-1]-w[i+a-1][j-1]-w[i-1][j+b-1]+w[i-1][j-1];
        }
    for(int i=1;i<=n-c+1;++i){
        int l=b-d+1;
        for(int j=1;j<l;++j){
            while(h<=t&&w1[i][j]<=q[t].s)--t;
            q[++t]={w1[i][j],j};
        }
        for(int j=l;j<=m-d+1;++j){
            while(h<=t&&j-q[h].id>=l-1)++h;
            x[i][j-l+1]=q[h].s;
            while(h<=t&&w1[i][j]<=q[t].s)--t;
            q[++t]={w1[i][j],j};
        }
        h=1,t=0;
    }
    for(int i=1;i<=m-b+1;++i){
        int l=a-c+1;
        for(int j=1;j<l;++j){
            while(h<=t&&x[j][i]<=q[t].s)--t;
            q[++t]={x[j][i],j};
        }
        for(int j=l;j<=n-c+1;++j){
            while(h<=t&&j-q[h].id>=l-1)++h;
            y[j-l+1][i]=q[h].s;
            while(h<=t&&x[j][i]<=q[t].s)--t;
            q[++t]={x[j][i],j};
        }
        h=1,t=0;
    }
    for(int i=1;i<=n-a+1;++i)
        for(int j=1;j<=m-b+1;++j)
            ans=max(ans,w2[i][j]-y[i][j]);
    printf("%d\n",ans);
    return 0;
}