您的位置:首页 > 其它

bzoj1047 理想的正方形

2016-01-16 23:00 260 查看

Description

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

Input

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

Output

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

水平方向用单调队列扫一次得出所有1*n区域的最大值和最小值

竖直方向再用单调队列扫一次上一部记录的最大值和最小值得出所有n*n区域的最大值和最小值

时间复杂度O(n2)

#include<cstdio>
int a,b,n,v[1024][1024];
int mx1[1024][1024],mn1[1024][1024];
int mx2[1024][1024],mn2[1024][1024];
struct{
int q[4096],qt[4096];
int qs,qe;
void clear(){
qs=qe=0;
}
void push(int x,int t){
while(qs<qe&&q[qe-1]<=x)--qe;
qt[qe]=t;
q[qe++]=x;
}
void chk(int p){
while(qs<qe&&qt[qs]<=p)qs++;
}
int max(){
return q[qs];
}
}q1;
struct{
int q[4096],qt[4096];
int qs,qe;
void clear(){
qs=qe=0;
}
void push(int x,int t){
while(qs<qe&&q[qe-1]>=x)--qe;
qt[qe]=t;
q[qe++]=x;
}
void chk(int p){
while(qs<qe&&qt[qs]<=p)qs++;
}
int min(){
return q[qs];
}
}q2;
int main(){
scanf("%d%d%d",&a,&b,&n);
for(int i=0;i<a;i++)
for(int j=0;j<b;j++)scanf("%d",v[i]+j);
for(int i=0;i<a;i++){
q1.clear();
q2.clear();
for(int j=0;j<n;j++)q1.push(v[i][j],j),q2.push(v[i][j],j);
mx1[i][n-1]=q1.max();
mn1[i][n-1]=q2.min();
for(int j=n;j<b;j++){
q1.push(v[i][j],j);
q1.chk(j-n);
mx1[i][j]=q1.max();
q2.push(v[i][j],j);
q2.chk(j-n);
mn1[i][j]=q2.min();
}
}
for(int j=0;j<b;j++){
q1.clear();
q2.clear();
for(int i=0;i<n;i++)q1.push(mx1[i][j],i),q2.push(mn1[i][j],i);
mx2[n-1][j]=q1.max();
mn2[n-1][j]=q2.min();
for(int i=n;i<a;i++){
q1.push(mx1[i][j],i);
q1.chk(i-n);
mx2[i][j]=q1.max();
q2.push(mn1[i][j],i);
q2.chk(i-n);
mn2[i][j]=q2.min();
}
}
int minv=2147483647;
for(int i=n-1;i<a;i++){
for(int j=n-1;j<b;j++){
if(mx2[i][j]-mn2[i][j]<minv)minv=mx2[i][j]-mn2[i][j];
}
}
printf("%d",minv);
return 0;
}
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: