n,m<=300,询问数<=1e6
给定n,m,一个n,m的矩阵,然后q组询问,每次询问给定一个子矩阵的左上坐标,右下坐标,求这个子矩阵的最大值。
蒟蒻先RE60,后发现边界处理有误,改完才AC
#include<cstdio> #include<iostream> using namespace std; int n,m,a[400][400]; int f[400][400][20][20]; int p; int r1,c1,r2,c2,k1,k2,ans; int main(){ // freopen("[图片]yy8.in","r",stdin); scanf("%d%d",&n,&m); for(int i=1;i<=n;i++){ for(int j=1;j<=m;j++){ scanf("%d",&a[i][j]); f[i][j][0][0]=a[i][j]; } } int u1=0,u2=0; while((1<<(u1+1))<=n)u1++; while((1<<(u2+1))<=m)u2++; for(int i=1;i<=n;i++){ for(int k=1;k<=u2;k++) for(int j=1;j+(1<<(k-1))<=m;j++){ f[i][j][0][k]=max(f[i][j][0][k-1],f[i][j+(1<<(k-1))][0][k-1]); } } for(int i=1;i<=m;i++){ for(int k=1;k<=u1;k++){ for(int j=1;j+(1<<(k-1))<=n;j++){ f[j][i][k][0]=max(f[j][i][k-1][0],f[j+(1<<(k-1))][i][k-1][0]); } } } for(int i=1;i<=u1;i++){ for(int j=1;j<=u2;j++){ for(int k=1;k+(1<<(i-1))<=n;k++){ for(int p=1;p+(1<<(j-1))<=m;p++){ f[k][p][i][j]=max(f[k][p][i][j],f[k][p][i-1][j-1]); f[k][p][i][j]=max(f[k][p][i][j],f[k+(1<<(i-1))][p][i-1][j-1]); f[k][p][i][j]=max(f[k][p][i][j],f[k][p+(1<<(j-1))][i-1][j-1]); f[k][p][i][j]=max(f[k][p][i][j],f[k+(1<<(i-1))][p+(1<<(j-1))][i-1][j-1]); //printf("%d %d %d %d %d\n",i,j,k,p,f[k][p][i][j]); } } } } scanf("%d",&p); while(p--){ scanf("%d%d%d%d",&r1,&c1,&r2,&c2); k1=k2=0; while((1<<(k1+1))<=(r2-r1+1)) k1++; while((1<<(k2+1))<=(c2-c1+1)) k2++; ans=0; ans=max(ans,f[r1][c1][k1][k2]); ans=max(ans,f[r2-(1<<k1)+1][c2-(1<<k2)+1][k1][k2]); ans=max(ans,f[r2-(1<<k1)+1][c1][k1][k2]); ans=max(ans,f[r1][c2-(1<<k2)+1][k1][k2]); printf("%d\n",ans); } return 0; }