POJ 2019 Cornfields(二维RMQ)
题目链接:传送门题目大意:给出一个n*n的矩阵,然后有k组询问,每组询问给出小矩阵的左上角的x,y。小矩阵的为b*b的矩阵,问这个小矩阵中最大值减最小值等于多少思路;二维RMQ记录每行每列的最大值最小值。即dpmax和dpmin用思维数组表示。#include<iostream>#include<stdio.h>#include&l
·
题目链接:传送门
题目大意:给出一个n*n的矩阵,然后有k组询问,每组询问给出小矩阵的左上角的x,y。小矩阵的为b*b的矩阵,问这个小矩阵中最大值减最小值等于多少
思路;二维RMQ记录每行每列的最大值最小值。
即dpmax和dpmin用思维数组表示。
#include<iostream>
#include<stdio.h>
#include<math.h>
#include<algorithm>
using namespace std;
#define maxn 300
int val[maxn][maxn];
int m[maxn];
int dpmax[maxn][maxn][10][10];
int dpmin[maxn][maxn][10][10];
int n;
void RMQ_init()
{
//int nlog=(int)(log(double(len))/log(2.0));
for(int i=1;i<=n;i++)
for(int j=1;j<=n;j++)
dpmax[i][j][0][0]=dpmin[i][j][0][0]=val[i][j];
for(int ii=0;ii<=m[n];ii++)
{
for(int jj=0;jj<=m[n];jj++)
{
if(ii+jj)
{
for(int i=1;i+(1<<ii)-1<=n;i++)
{
for(int j=1;j+(1<<jj)-1<=n;j++)
{
if(ii)
{
dpmin[i][j][ii][jj]=min(dpmin[i][j][ii-1][jj],dpmin[i+(1<<(ii-1))][j][ii-1][jj]);
dpmax[i][j][ii][jj]=max(dpmax[i][j][ii-1][jj],dpmax[i+(1<<(ii-1))][j][ii-1][jj]);
}
else
{
dpmin[i][j][ii][jj]=min(dpmin[i][j][ii][jj-1],dpmin[i][j+(1<<(jj-1))][ii][jj-1]);
dpmax[i][j][ii][jj]=max(dpmax[i][j][ii][jj-1],dpmax[i][j+(1<<(jj-1))][ii][jj-1]);
}
}
}
}
}
}
}
int RMQ_Query(int x1,int y1,int x2,int y2)
{
int k1=m[x2-x1+1];
int k2=m[y2-y1+1];
x2=x2-(1<<k1)+1;
y2=y2-(1<<k2)+1;
int ma=max(max(dpmax[x1][y1][k1][k2],dpmax[x1][y2][k1][k2]),max(dpmax[x2][y1][k1][k2],dpmax[x2][y2][k1][k2]));
int mi=min(min(dpmin[x1][y1][k1][k2],dpmin[x1][y2][k1][k2]),min(dpmin[x2][y1][k1][k2],dpmin[x2][y2][k1][k2]));
return ma-mi;
}
int main()
{
m[0]=-1;
for(int i=1;i<500;i++)
{
m[i]=((i&(i-1))==0)?m[i-1]+1:m[i-1];
}
int b,k;
while(~scanf("%d%d%d",&n,&b,&k))
{
for(int i=1;i<=n;i++)
{
for(int j=1;j<=n;j++)
{
cin>>val[i][j];
}
}
RMQ_init();
while(k--)
{
int l,r;
cin>>l>>r;
printf("%d\n",RMQ_Query(l,r,l+b-1,r+b-1));
}
}
return 0;
}
更多推荐
已为社区贡献1条内容
所有评论(0)