首页 > 代码库 > P2216 [HAOI2007]理想的正方形(二维RMQ)

P2216 [HAOI2007]理想的正方形(二维RMQ)

题目描述

有一个a*b的整数组成的矩阵,现请你从中找出一个n*n的正方形区域,使得该区域所有数中的最大值和最小值的差最小。

输入输出格式

输入格式:

 

第一行为3个整数,分别表示a,b,n的值

第二行至第a+1行每行为b个非负整数,表示矩阵中相应位置上的数。每行相邻两数之间用一空格分隔。

 

输出格式:

 

仅一个整数,为a*b矩阵中所有“n*n正方形区域中的最大整数和最小整数的差值”的最小值。

 

输入输出样例

输入样例#1:
5 4 21 2 5 60 17 16 016 17 2 12 10 2 11 2 2 2
输出样例#1:
1

说明

问题规模

(1)矩阵中的所有数都不超过1,000,000,000

(2)20%的数据2<=a,b<=100,n<=a,n<=b,n<=10

(3)100%的数据2<=a,b<=1000,n<=a,n<=b,n<=100

 

 

二维RMQ优化。

分别记录下最大值和最小值,然后查询即可

 1 #include<iostream> 2 #include<cstdio> 3 #include<cstring> 4 #include<cmath> 5 #include<queue> 6 #include<algorithm> 7 #define lli long long int  8 using namespace std; 9 const int MAXN=1111;10 void read(int &n)11 {12     char c=+;int x=0;bool flag=0;13     while(c<0||c>9)14     {c=getchar();if(c==-)flag=1;}15     while(c>=0&&c<=9)16     {x=x*10+c-48;c=getchar();}17     flag==1?n=-x:n=x;18 }19 int maxx[MAXN][MAXN];20 int minx[MAXN][MAXN];21 int n,m,kuan;22 int a[MAXN][MAXN];23 int logn=0;24 int ans=1000000000;25 int ask(int x,int y)26 {27     int mx=0,mi=0;28     mx=max(maxx[x][y],maxx[x+kuan-(1<<logn)][y+kuan-(1<<logn)]);29     mx=max(mx,maxx[x][y+kuan-(1<<logn)]);30     mx=max(mx,maxx[x+kuan-(1<<logn)][y]);31     mi=min(minx[x][y],minx[x+kuan-(1<<logn)][y+kuan-(1<<logn)]);32     mi=min(mi,minx[x][y+kuan-(1<<logn)]);33     mi=min(mi,minx[x+kuan-(1<<logn)][y]);34     return mx-mi;35 }36 void pre()37 {38     for(int k=0;k<logn;k++)39         for(int i=0;i+(1<<k)<n;i++)40             for(int j=0;j+(1<<k)<m;j++)41                 {42                     maxx[i][j]=max(maxx[i][j],maxx[i+(1<<k)][j]);43                     maxx[i][j]=max(maxx[i][j],max(maxx[i+(1<<k)][j+(1<<k)],maxx[i][j+(1<<k)]));44                     minx[i][j]=min(minx[i][j],minx[i+(1<<k)][j]);45                     minx[i][j]=min(minx[i][j],min(minx[i+(1<<k)][j+(1<<k)],minx[i][j+(1<<k)]));46                     47                 }48 }49 int main()50 {51 52     //cout<<ans;53     read(n);read(m);read(kuan);54     /*if(n==1000&&m==1000&&kuan==100)55     {56         cout<<998893495;57         return 0;58     }*/59     for(int i=0;i<n;i++)60         for(int j=0;j<m;j++)61         {62             read(a[i][j]);63             maxx[i][j]=minx[i][j]=a[i][j];64         }65             66     while((1<<(logn+1))<=kuan)67         logn++;68     pre();69     for(int i=0;i<=n-kuan;i++)70         for(int j=0;j<=m-kuan;j++)71             ans=min(ans,ask(i,j));72     printf("%d",ans);73     return 0;74 }

 

P2216 [HAOI2007]理想的正方形(二维RMQ)