POJ 2019 Cornfields(二维RMQ)

题目链接:传送门

题目大意:给出一个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;
}
​

猜你喜欢

转载自blog.csdn.net/qq_36782366/article/details/81176464