ZOJ 2859 Matrix Searching(二维RMQ)

来源:互联网 发布:数据采集器编程 编辑:程序博客网 时间:2024/05/18 03:17

二维的相当于先求出每一行i的每一列j开始到j+2^j-1最值,然后求各个行和列之间的最值

#include <iostream>#include <cstdio>#include <cmath>#include <memory.h>using namespace std;#define mmin(a,b) (a)<(b)?(a):(b);const int maxn=310;int dp[maxn][maxn][9][9],grid[maxn][maxn],n,q;void init(){for(int i=0;i<n;++i){for (int j=0;j<n;++j){dp[i][j][0][0]=grid[i][j];}}int k=log(n*1.0)/log(2.0);for(int i=0;i<=k;++i){//行for (int j=0;j<=k;++j){//列if(i==0&&j==0)continue;for (int ii=0;ii+(1<<i)-1<n;++ii){//for (int jj=0;jj+(1<<j)-1<n;++jj){if(i==0){//初始i等于0的时候相当于把每一行的一维的最值算出来dp[ii][jj][i][j]=mmin(dp[ii][jj][i][j-1],dp[ii][jj+(1<<(j-1))][i][j-1]);}else{//因为每一行的各个列开始的最值已经全部求出来,现在相当于计算各行各列之间的最值dp[ii][jj][i][j]=mmin(dp[ii][jj][i-1][j],dp[ii+(1<<(i-1))][jj][i-1][j]);}}}}}}int query(int x1,int x2,int y1,int y2){int k_x=log(x2-x1+1.0)/log(2.0);int k_y=log(y2-y1+1.0)/log(2.0);//下面的操作相当于把这个二维区间分割成了4个部分重叠的方块,然后求这4个方块的最值int v1=mmin(dp[x1][y1][k_x][k_y],dp[x2-(1<<k_x)+1][y1][k_x][k_y]);int v2=mmin(dp[x1][y2-(1<<k_y)+1][k_x][k_y],dp[x2-(1<<k_x)+1][y2-(1<<k_y)+1][k_x][k_y]);return mmin(v1,v2);}int main(){int t;scanf("%d",&t);while (t--){scanf("%d",&n);for (int i=0;i<n;++i){for (int j=0;j<n;++j){scanf("%d",&grid[i][j]);}}init();scanf("%d",&q);while (q--){int x1,x2,y1,y2;scanf("%d%d%d%d",&x1,&y1,&x2,&y2);printf("%d\n",query(x1-1,x2-1,y1-1,y2-1));}}return 0;}