【Ybtoj 第16章例4】矩阵最值【RMQ问题】

在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述


解题思路
这是二维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=0f[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>0f[i][j][k][h]=max(f[i][j][k1][h],f[i+(1<<(k1))][j][k1][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>0f[i][j][k][h]=max(f[i][j][k][h1],f[i][j+(1<<(h1))][k][h1]);

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[x2x1+1],k2=log[y2y1+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])));
	}
} 
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值