您的位置:首页 > 其它

【二维RMQ】hdu 2888 Check Corners

2015-10-18 14:05 344 查看
http://acm.hdu.edu.cn/showproblem.php?pid=2888

二维RMQ,支持静态查询区间最值(最小或最大)

/*
hdu 2888 二维RMQ
二维RMQ,支持静态查询,预处理O(n*m*lgn*lgm)
下标从1开始
注意与二维线段树的区别(支持动态更新)
*/
#include<iostream>
#include<cstdio>
#include<cstdlib>
#include<cmath>
#include<cstring>
#include<vector>
#include<set>
#include<map>
#include<algorithm>
#include<sstream>
#define eps 1e-9
#define pi acos(-1)
#define INF 0x7fffffff
#define inf -INF
#define MM 10
#define N 1010
using namespace std;
typedef long long ll;
const int _max = 300 + 10;

int val[310][310];
int dp[310][310][9][9];
int mm[310];

int n,m,Q;

void initRMQ(int n,int m){
for(int i = 1; i <= n; ++ i)
for(int j = 1;j <= m;++j)
dp[i][j][0][0]=val[i][j];
for(int ii = 0; ii <= mm
;++ ii)
for(int jj = 0; jj <= mm[m]; ++ jj)
if(ii+jj)
for(int i =1;i + (1<<ii)-1<=n; ++ i)
for(int j = 1;j+(1<<jj)-1<=m;++j){
if(ii)dp[i][j][ii][jj]=max(dp[i][j][ii-1][jj],dp[i+(1<<(ii-1))][j][ii-1][jj]);
else dp[i][j][ii][jj]=max(dp[i][j][ii][jj-1],dp[i][j+(1<<(jj-1))][ii][jj-1]);
}
}
//rmq查询(x1<=x2,y1<=y2)
int rmq(int x1,int y1,int x2,int y2){
int k1= mm[x2-x1+1];
int k2 = mm[y2-y1+1];
x2=x2-(1<<k1)+1;
y2=y2-(1<<k2)+1;
return max(max(dp[x1][y1][k1][k2],dp[x1][y2][k1][k2]),max(dp[x2][y1][k1][k2],dp[x2][y2][k1][k2]));
}

int main()
{
#ifndef ONLINE_JUDGE
freopen("input.txt","r",stdin);
#endif // ONLINE_JUDGE
//mm数组初始化
mm[0]=-1;
for(int i = 1; i <= 810; ++ i)
mm[i]=((i&(i-1))==0)?mm[i-1]+1:mm[i-1];
while(scanf("%d%d",&n,&m)==2){
for(int i = 1; i <= n; ++ i)
for(int j = 1;j <= m; ++ j)
scanf("%d",&val[i][j]);
int r1,c1,r2,c2,maxx;
initRMQ(n,m);
scanf("%d",&Q);
while(Q--){
scanf("%d%d%d%d",&r1,&c1,&r2,&c2);
if(r1>r2)swap(r1,r2);
if(c1>c2)swap(c1,c2);
maxx = rmq(r1,c1,r2,c2);
printf("%d ",maxx);
bool ok = (maxx==val[r1][c1])||(maxx==val[r1][c2])||(maxx==val[r2][c1])||(maxx==val[r2][c2]);
puts(ok?"yes":"no");
}
}
return 0;
}
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签:  二维RMQ