这道题跟很像,不大明白蛤OI是怎么想的,一年出两道这么相近的题
这道题有两个矩形,所以就有了两种做法(说是两种做法,其实只是维护的矩形不同)
一种是维护大矩形,一种是维护小矩形,我这里采取了维护小矩形的方法
先求出以\((i,j)\)为左上角的大矩形和小矩形的权值和为多少,然后用单调队列维护以(i,j)为左上角的大矩形里能放得最小的小矩形是哪个,最后做差得答案即可
下面是代码
#include#include #include #include #include #define ll long long#define gc getchar#define maxn 1005using 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-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-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;}