二维RMQ问题
题意是输入一个N*N的方阵,和K条指令,每条指令是一个B*B子方阵的左上角元素坐标,对于每一条指令,让求出这个子方阵的最大值与最小值之差。
套二维RMQ模板即可,和HDU2888一样,详细可以看上一篇文章。
#include <cstdio>
#include <cmath>
#include <cstring>
#include <iostream>
using namespace std;
int f[252][252][9][9];//纪录最大值;
int f1[252][252][9][9];//纪录最小值;
int num[252][252];
int n;
void init_RMQ()
{
int i,j,r,c;
for(i=1;i<=n;i++)
for(j=1;j<=n;j++)
{
f[i][j][0][0]=num[i][j];
f1[i][j][0][0]=num[i][j];
}
int kr=(int)(log((double)n)/log(2.0));
int kc=kr;
for(i=0;i<=kr;i++)
for(j=0;j<=kc;j++)
{
if(i==0&&j==0) continue;
for(r=1;r+(1<<i)-1<=n;r++)
for(c=1;c+(1<<j)-1<=n;c++)
if(i==0)
{
f[r][c][i][j]=max(f[r][c][i][j-1],f[r][c+(1<<(j-1))][i][j-1]);
f1[r][c][i][j]=min(f1[r][c][i][j-1],f1[r][c+(1<<(j-1))][i][j-1]);
}
else
{
f[r][c][i][j]=max(f[r][c][i-1][j],f[r+(1<<(i-1))][c][i-1][j]);
f1[r][c][i][j]=min(f1[r][c][i-1][j],f1[r+(1<<(i-1))][c][i-1][j]);
}
}
}
int RMQ(int r1,int c1,int r2,int c2)
{
int kr=(int)(log(double(r2-r1+1))/log(2.0));
int kc=(int)(log(double(c2-c1+1))/log(2.0));
return max(max(f[r1][c1][kr][kc],f[r2-(1<<kr)+1][c1][kr][kc]),max(f[r1][c2-(1<<kc)+1][kr][kc],f[r2-(1<<kr)+1][c2-(1<<kc)+1][kr][kc]));
}
int RMQ1(int r1,int c1,int r2,int c2)
{
int kr=(int)(log(double(r2-r1+1))/log(2.0));
int kc=(int)(log(double(c2-c1+1))/log(2.0));
return min(min(f1[r1][c1][kr][kc],f1[r2-(1<<kr)+1][c1][kr][kc]),min(f1[r1][c2-(1<<kc)+1][kr][kc],f1[r2-(1<<kr)+1][c2-(1<<kc)+1][kr][kc]));
}
int main()
{
int b,k;
while(scanf("%d%d%d",&n,&b,&k)!=-1)
{
for(int i=1;i<=n;i++)
for(int j=1;j<=n;j++)
scanf("%d",&num[i][j]);
init_RMQ();
int t,r1,c1,r2,c2;
while(k--)
{
scanf("%d%d",&r1,&c1);
r2=r1+b-1;
c2=c1+b-1;
printf("%d\n",RMQ(r1,c1,r2,c2)-RMQ1(r1,c1,r2,c2));
}
}
return 0;
}