解题思路
这是二维st表的模板题,设f_{i,j,k,h}表示左上角为(i,j),右下角为(i+2k-1,j+2h-1)的矩阵的最大值。
转移方程:
- 当 k = h = 0 , f [ i ] [ j ] [ k ] [ h ] = a [ i ] [ j ] k=h=0,f[i][j][k][h]=a[i][j] k=h=0,f[i][j][k][h]=a[i][j]
- 当 k > 0 , f [ i ] [ j ] [ k ] [ h ] = m a x ( f [ i ] [ j ] [ k − 1 ] [ h ] , f [ i + ( 1 < < ( k − 1 ) ) ] [ j ] [ k − 1 ] [ h ] ) ; k>0,f[i][j][k][h]=max(f[i][j][k-1][h],f[i+(1<<(k-1))][j][k-1][h]); k>0,f[i][j][k][h]=max(f[i][j][k−1][h],f[i+(1<<(k−1))][j][k−1][h]);
- 当 h > 0 , f [ i ] [ j ] [ k ] [ h ] = m a x ( f [ i ] [ j ] [ k ] [ h − 1 ] , f [ i ] [ j + ( 1 < < ( h − 1 ) ) ] [ k ] [ h − 1 ] ) ; h>0,f[i][j][k][h]=max(f[i][j][k][h-1],f[i][j+(1<<(h-1))][k][h-1]); h>0,f[i][j][k][h]=max(f[i][j][k][h−1],f[i][j+(1<<(h−1))][k][h−1]);
设 k 1 = l o g [ x 2 − x 1 + 1 ] , k 2 = l o g [ y 2 − y 1 + 1 ] k_1=log[x_2-x_1+1],k_2=log[y_2-y_1+1] k1=log[x2−x1+1],k2=log[y2−y1+1]
则 a n s = m a x ( m a x ( f [ x 1 ] [ y 1 ] [ k 1 ] [ k 2 ] , f [ x 2 − ( 1 < < k 1 ) + 1 ] [ y 1 ] [ k 1 ] [ k 2 ] ) , m a x ( f [ x 1 ] [ y 2 − ( 1 < < k 2 ) + 1 ] [ k 1 ] [ k 2 ] , f [ x 2 − ( 1 < < k 1 ) + 1 ] [ y 2 − ( 1 < < k 2 ) + 1 ] [ k 1 ] [ k 2 ] ) ) ans=max(max(f[x_1][y_1][k_1][k_2],f[x_2-(1<<k_1)+1][y_1][k_1][k_2]),max(f[x_1][y_2-(1<<k_2)+1][k_1][k_2],f[x_2-(1<<k_1)+1][y_2-(1<<k_2)+1][k_1][k_2])) ans=max(max(f[x1][y1][k1][k2],f[x2−(1<<k1)+1][y1][k1][k2]),max(f[x1][y2−(1<<k2)+1][k1][k2],f[x2−(1<<k1)+1][y2−(1<<k2)+1][k1][k2]))
代码
#include<iostream>
#include<cstdio>
#include<iomanip>
#include<cstring>
#include<algorithm>
#include<cmath>
#include<queue>
using namespace std;
int n,m,K,x1,yy,x2,y2,a[300][300],f[300][300][20][20],lg[20];
int main(){
scanf("%d%d%d",&n,&m,&K);
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];
}
}
lg[0]=-1;
for(int i=1;i<=max(n,m);i++)
lg[i]=lg[i>>1]+1;
for(int k=0;k<=lg[n];k++)
{
for(int h=0;h<=lg[m];h++)
{
if(!k&&!h)continue;
for(int i=1;i+(1<<k)-1<=n;i++)
{
for(int j=1;j+(1<<h)-1<=m;j++)
{
if(k)
f[i][j][k][h]=max(f[i][j][k-1][h],f[i+(1<<(k-1))][j][k-1][h]);
else f[i][j][k][h]=max(f[i][j][k][h-1],f[i][j+(1<<(h-1))][k][h-1]);
}
}
}
}
for(int i=1;i<=K;i++)
{
scanf("%d%d%d%d",&x1,&yy,&x2,&y2);
int k1=lg[x2-x1+1],k2=lg[y2-yy+1];
printf("%d\n",max(max(f[x1][yy][k1][k2],f[x2-(1<<k1)+1][yy][k1][k2]),
max(f[x1][y2-(1<<k2)+1][k1][k2],f[x2-(1<<k1)+1][y2-(1<<k2)+1][k1][k2])));
}
}