題目鏈接:https://www.luogu.org/problem/P2219
emmm調了一個上午+中午,fan
題意:從N*M的中找到一個a*b的大矩形和減去a*b中的一個與之不重邊界的c*d的小矩形和最大
二維處理前綴和兩次,分別是處理出以i,j爲右下角的a*b矩形和A[i][j],以c*d矩形和B[i][j];
然後我們以B[i][j]的每一行行進行單調隊列維護一個j-b+d-2~j的最小值 P[i][j]
再以P[i][j]的每一列維護一個從i-a+c-2~i的單調隊列T[i][j]
因爲不重邊 所以ans=min(A[i][j]-T[i-1][j-1]) (i>=a&&j>=b)
OVER !但是我還是wa了一上午
因爲維護某個數長度k最小值的時候,前k個可能都是0,這個時候維護一個長度k+1的單調隊列就不會出現第一個應該取他本身但是誤取了0的錯誤算法 ~太笨了
十分可惜的代碼如下:
//#pragma comment (linker, "/STACK:102400000,102400000")
#include<bits/stdc++.h>
#include<stdio.h>
#include<string.h>
#include<string>
#include<iostream>
#include<algorithm>
#include<math.h>
#include<set>
#include<stack>
#include<vector>
#include<map>
#include<queue>
#include<list>
#include<time.h>
#include<bitset>
#define myself i,l,r
#define lson i<<1
#define rson i<<1|1
#define Lson i<<1,l,mid
#define Rson i<<1|1,mid+1,r
#define half (l+r)/2
#define lowbit(x) x&(-x)
#define min4(a, b, c, d) min(min(a,b),min(c,d))
#define min3(x, y, z) min(min(x,y),z)
#define max3(x, y, z) max(max(x,y),z)
#define max4(a, b, c, d) max(max(a,b),max(c,d))
#define pii make_pair
#define pr pair<int,int>
typedef unsigned long long ull;
typedef long long ll;
const int inff = 0x3f3f3f3f;
const long long inFF = 9223372036854775807;
const int dir[4][2] = {0, 1, 0, -1, 1, 0, -1, 0};
const int mdir[8][2] = {0, 1, 0, -1, 1, 0, -1, 0, 1, 1, -1, 1, 1, -1, -1, -1};
const double eps = 1e-10;
const double PI = acos(-1.0);
const double E = 2.718281828459;
using namespace std;
const int mod=1e9+7;
const int maxn=1005;
int s[maxn][maxn],A[maxn][maxn],B[maxn][maxn];
int P[maxn][maxn],T[maxn][maxn];
int q[maxn];
int main()
{
int n,m,a,b,c,d;
cin>>n>>m>>a>>b>>c>>d;
for(int i=1;i<=n;i++)
for(int j=1;j<=m;j++)
scanf("%d",&s[i][j]);
for(int i=1;i<=n;i++)
for(int j=1;j<=m;j++)
s[i][j]+=s[i-1][j]+s[i][j-1]-s[i-1][j-1];
for(int i=a;i<=n;i++)
for(int j=b;j<=m;j++)
A[i][j]=s[i][j]-s[i-a][j]-s[i][j-b]+s[i-a][j-b];//A表示大矩形和
for(int i=c+1;i<n;i++)
for(int j=d+1;j<m;j++)
B[i][j]=s[i][j]-s[i-c][j]-s[i][j-d]+s[i-c][j-d];//小矩形和
// for(int i=1;i<=n;i++)
// {
// for(int j=1;j<=m;j++)
// cout<<A[i][j]<<" ";
// cout<<endl;
// }
// cout<<endl;
// for(int i=1;i<=n;i++)
// {
// for(int j=1;j<=m;j++)
// cout<<B[i][j]<<" ";
// cout<<endl;
// }
// cout<<endl;
for(int i=c+1;i<n;i++)
{
int l=1,r=0;
for(int j=d+1;j<m;j++)//P維護一段小矩形行的單調隊列,j位置維護 j-b+d+1~j-1,單調隊列區間長度爲b-d-2;
{
while(l<=r&&q[l]<j-b+d+2) l++;
while(l<=r&&B[i][q[r]]>=B[i][j]) r--;
q[++r]=j;
P[i][j]=B[i][q[l]];
}
}
// for(int i=1;i<=n;i++)
// {
// for(int j=1;j<=m;j++)
// cout<<P[i][j]<<" ";
// cout<<endl;
// }
// cout<<endl;
for(int j=c+1;j<m;++j)
{
int l=1,r=0;
for(int i=c+1;i<n;i++)
{
while(l<=r&&P[q[r]][j]>=P[i][j]) r--;
q[++r]=i;
while(l<=r&&q[l]<i-a+c+2) l++;
T[i][j]=P[q[l]][j];
}
}
// for(int i=1;i<=n;i++)
// {
// for(int j=1;j<=m;j++)
// cout<<T[i][j]<<" ";
// cout<<endl;
// }
// cout<<endl;
int ans=0;
for(int i=a;i<=n;i++)
for(int j=b;j<=m;j++)
ans=max(ans,A[i][j]-T[i-1][j-1]);
cout<<ans<<endl;
}
/*
4 5 4 4 1 1
1 2 3 4 5
6 7 8 9 10
11 12 13 14 15
16 17 18 19 20
*/