poj2019 二维RMQ模板题

和hdu2888基本上一样的,也是求一个矩阵内的极值

#include<iostream>
#include<cstring>
#include<cstdio>
#include<algorithm>
#include<cmath>
using namespace std;
#define maxn 252
int n,b,q;
int dpmax[maxn][maxn][9][9],dpmin[maxn][maxn][9][9],val[maxn][maxn];
void ST(){
    int k=log2(n);
    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 i=0;i<=k;i++)//先求出一行内的最大值和最小值,然后再求出行间的最大值和最小值
        for(int j=0;j<=k;j++){
            if(i==0 && j==0) continue;
            for(int r=1;r+(1<<i)-1<=n;r++)
                for(int c=1;c+(1<<j)-1<=n;c++)
                    if(i==0){//在同一行内
                        dpmax[r][c][i][j]=max(dpmax[r][c][i][j-1],dpmax[r][c+(1<<(j-1))][i][j-1]);
                        dpmin[r][c][i][j]=min(dpmin[r][c][i][j-1],dpmin[r][c+(1<<(j-1))][i][j-1]);
                    }
                    else {
                        dpmax[r][c][i][j]=max(dpmax[r][c][i-1][j],dpmax[r+(1<<(i-1))][c][i-1][j]);
                        dpmin[r][c][i][j]=min(dpmin[r][c][i-1][j],dpmin[r+(1<<(i-1))][c][i-1][j]);
                    }
        }
}
int query(int r,int c){
    int r1=r,c1=c,r2=r+b-1,c2=c+b-1,k=log2(b);
    int max1=dpmax[r1][c1][k][k];
    int max2=dpmax[r2-(1<<k)+1][c1][k][k];
    int max3=dpmax[r1][c2-(1<<k)+1][k][k];
    int max4=dpmax[r2-(1<<k)+1][c2-(1<<k)+1][k][k];
    int min1=dpmin[r1][c1][k][k];
    int min2=dpmin[r2-(1<<k)+1][c1][k][k];
    int min3=dpmin[r1][c2-(1<<k)+1][k][k];
    int min4=dpmin[r2-(1<<k)+1][c2-(1<<k)+1][k][k];
    return max(max(max1,max2),max(max3,max4))-min(min(min1,min2),min(min3,min4));
}
int main(){
    while(scanf("%d%d%d",&n,&b,&q)==3){
        for(int i=1;i<=n;i++)
            for(int j=1;j<=n;j++) scanf("%d",&val[i][j]);
        ST();int r,c;
        while(q--){
            scanf("%d%d",&r,&c);
            printf("%d
",query(r,c));
        }
    }
    return 0;
}
原文地址:https://www.cnblogs.com/zsben991126/p/10031546.html