水题?火题?
关键在于坐标循环边界的确定。
1 // luogu-judger-enable-o2 2 #include <bits/stdc++.h> 3 using namespace std; 4 5 struct Monoque{ 6 int head,tail,q[2005],qt[2005]; 7 Monoque() { 8 head=0; 9 tail=-1; 10 memset(q,0,sizeof q); 11 } 12 void push(int val,int tim) { 13 while(q[tail]>=val && head<=tail) tail--; 14 q[++tail]=val; 15 qt[tail]=tim; 16 } 17 int front(int tim) { 18 if(head>tail) return 1e+5; 19 while(qt[head]<tim && head<=tail) head++; 20 if(head>tail) return 1e+5; 21 return q[head]; 22 } 23 } p[2005],q[2005]; 24 25 int n,m,a,b,c,d,x[1005][1005],y[1005][1005],w[1005][1005],z[1005][1005],s[1005][1005],ans=0; 26 27 int rect(int l1,int r1,int l2,int r2) { 28 l1--; r1--; 29 return s[l2][r2]-s[l1][r2]-s[l2][r1]+s[l1][r1]; 30 } 31 32 int main(){ 33 ios::sync_with_stdio(false); 34 cin>>n>>m>>a>>b>>c>>d; 35 for(int i=1;i<=n;i++) 36 for(int j=1;j<=m;j++) 37 cin>>x[i][j], 38 s[i][j]=s[i-1][j]+s[i][j-1]-s[i-1][j-1]+x[i][j]; 39 for(int i=1;i<=n-a+1;i++) 40 for(int j=1;j<=m-b+1;j++) 41 x[i][j]=rect(i,j,i+a-1,j+b-1); 42 for(int i=1;i<=n-c+1;i++) 43 for(int j=1;j<=m-d+1;j++) 44 w[i][j]=rect(i,j,i+c-1,j+d-1); 45 // time : a-c b-d 46 for(int i=1;i<=n-c+1;i++) { 47 for(int j=1;j<=m-d+1;j++) { 48 z[i][j]=q[j].front(i); 49 q[j].push(p[i].front(j),i+a-c-1); 50 p[i].push(w[i][j],j+b-d-1); 51 } 52 } 53 for(int i=1;i<=n-a+1;i++) { 54 for(int j=1;j<=m-b+1;j++) { 55 //printf("i=%d j=%d %d,%d x=%d z=%d\n",i,j,i+a-c,j+b-d,x[i][j],z[i+a-c][j+b-d]); 56 ans=max(ans,x[i][j]-z[i+a-c][j+b-d]); 57 } 58 } 59 cout<<ans<<endl; 60 }