您的位置:首页 > 其它

BZOJ 1047 [HAOI2007]理想的正方形

2015-08-13 14:37 423 查看

1047: [HAOI2007]理想的正方形

Time Limit: 10 Sec Memory Limit: 162 MB
Submit: 2054 Solved: 1091
[Submit][Status][Discuss]

Description

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

Input

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

Output

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

Sample Input

5 4 2

1 2 5 6

0 17 16 0

16 17 2 1

2 10 2 1

1 2 2 2

Sample Output

1

HINT

问题规模

(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

Source

题解:太神了,膜郑爷%%%

首先看数据范围,很显然要求线性算法,那就是说只能扫一次喽,那就是说要O(1)维护喽,那就是说要敲单调队列喽。。。

既然要写moque,就要着重考虑一下啥时候该删除了。首先把窝萌的查询的框分成4部分:

假设窝萌的小正方形从左上角往下动,那么很显然1区域对于两个方向只是添加,2区域对于y方向是增加,对于x方向是维护,3区域对于x方向是增加,对于y方向是维护,4区域对于两个方向都是维护。

那就好办呀,对于不同的部分用不同的办法维护不就好了。。。。

注意这里有个细节:比如窝萌维护1区域的时候一定是1~n-1!!!为啥?因为i=n的时候就需要开始回答了!

然后说一下单调队列:窝萌还需要记录一下进队的时间,用来维护pop操作。然后就码就行了。。。

#include<iostream>
#include<cstdio>
#include<cmath>
#include<algorithm>
#include<stack>
#include<queue>
#include<cstring>
#define PAU putchar(' ')
#define ENT putchar('\n')
using namespace std;
const int maxn=1000+10,inf=-1u>>1;
struct moque{
int a1[1001],t1[1001],a2[1001],t2[1001];
int st1,ed1,st2,ed2;
moque(){st1=1;ed1=0;st2=1;ed2=0;}
void pushmi(int x,int t){
while((st1<=ed1)&&(x<=a1[ed1]))ed1--;ed1++;a1[ed1]=x;t1[ed1]=t;return;
}
void pushmx(int x,int t){
while((st2<=ed2)&&(x>=a2[ed2]))ed2--;ed2++;a2[ed2]=x;t2[ed2]=t;return;
}
void pop(int t){
if(t1[st1]==t)st1++;if(t2[st2]==t)st2++;return;
}
int qmin(){return a1[st1];}
int qmax(){return a2[st2];}
}qx[maxn],qy[maxn];
int a,b,n,A[maxn][maxn];
inline int read(){
int x=0,sig=1;char ch=getchar();
for(;!isdigit(ch);ch=getchar())if(ch=='-')sig=0;
for(;isdigit(ch);ch=getchar())x=10*x+ch-'0';
return sig?x:-x;
}
inline void write(int x){
if(x==0){putchar('0');return;}if(x<0)putchar('-'),x=-x;
int len=0,buf[15];while(x)buf[len++]=x%10,x/=10;
for(int i=len-1;i>=0;i--)putchar(buf[i]+'0');return;
}
int main(){
a=read();b=read();n=read();
for(int i=1;i<=a;i++)for(int j=1;j<=b;j++)A[i][j]=read();
for(int i=1;i<n;i++){
for(int j=1;j<n;j++)qx[i].pushmi(A[i][j],j),qx[i].pushmx(A[i][j],j);
for(int j=n;j<=b;j++){
qx[i].pushmi(A[i][j],j);qx[i].pushmx(A[i][j],j);
qy[j].pushmi(qx[i].qmin(),i);qy[j].pushmx(qx[i].qmax(),i);
qx[i].pop(j-n+1);
}
}int ans=inf;
for(int i=n;i<=a;i++){
for(int j=1;j<n;j++)qx[i].pushmi(A[i][j],j),qx[i].pushmx(A[i][j],j);
for(int j=n;j<=b;j++){
qx[i].pushmi(A[i][j],j);qx[i].pushmx(A[i][j],j);
qy[j].pushmi(qx[i].qmin(),i);qy[j].pushmx(qx[i].qmax(),i);
ans=min(ans,qy[j].qmax()-qy[j].qmin());
qx[i].pop(j-n+1);qy[j].pop(i-n+1);
}
}write(ans);
return 0;
}
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: