题目描述 众所周知,正方形是很美妙的图形。当然了,LJH也很喜欢正方形。
正方形的四条边均相等,四个内角均等于90度,对边分别平行,既是中心对称图形,又是轴对称图形,绕中心旋转90度图形不变。
正方形有这么多美轮美奂的性质,又岂是矩形能比的?所以,当LJH看着一堆矩形时,他心里犯了愁。 “把矩形剪成正方形不就得了。”LJH灵机一动。
当然,LJH既然是处女座,自然不会满足于那些普通的正方形。他要求选出的正方形的四条边都与矩形的边平行,并且边长为n。同时,因为这些矩形是由a*b个自然数组成的,所以LJH希望选出的正方形中,最大值与最小值的差尽量小。他认为这样的正方形很“理想”。
当然了,LJH非常忙(lan),他把任务交给了你,你能帮帮他吗?输入 第一行3个整数,a,b,n,含义如题目描述。 接下来a行,每行b个自然数,描述一个矩形数阵。
输出 输出只有一个自然数,表示为a*b矩阵中所有n*n正方形区域中的最大整数和最小整数的差的最小值。
样例输入
5 4 2
1 2 5 6
0 17 16 0
16 17 2 1
2 10 2 1
1 2 2 2
样例输出
1
提示
【注释及数据范围】样例中选取左上角左边为(3,3)或(4,3)的正方形均满足要求。
20%的数据满足a,b<=100,n<=10,时限1s
50%的数据满足a,b<=600,n<=80,时限3s
100%的数据满足,2<=a,b<=2000,n<=a,n<=b,n<=100,所有自然数均不大于10^9,时限5s
读入文件可能很大,c++选手请用scanf读入
由于要求的正方形边长固定,我们可以用单调队列优化,求行的区间最值,求列的区间最值,就可以计算答案了。详见代码。
var
mini,maxn,maxh,minh:array[-100..2000,-100..2000] of longint;
qmax,qmin,tmin,tmax:array[-100..2000] of longint;
lmax,rmax,rmin,lmin,ans,i,j,a,b,n,x:longint;
procedure ins_max(x:longint);
begin
if tmax[lmax]=0 then inc(lmax)
else dec(tmax[lmax]);
inc(rmax);
qmax[rmax]:=x;
while (qmax[rmax]>qmax[rmax-1])and(rmax-1>=lmax) do
begin
dec(rmax);
qmax[rmax]:=qmax[rmax+1];
tmax[rmax]:=tmax[rmax]+1+tmax[rmax+1];
tmax[rmax+1]:=0;
end;
end;
procedure ins_min(x:longint);
begin
if tmin[lmin]=0 then inc(lmin)
else dec(tmin[lmin]);
inc(rmin);
qmin[rmin]:=x;
while (qmin[rmin]<qmin[rmin-1])and(rmin-1>=lmin) do
begin
dec(rmin);
qmin[rmin]:=qmin[rmin+1];
tmin[rmin]:=tmin[rmin]+1+tmin[rmin+1];
tmin[rmin+1]:=0;
end;
end;
procedure ql;
begin
fillchar(qmin,sizeof(qmin),0);
fillchar(qmax,sizeof(qmax),0);
fillchar(tmin,sizeof(tmin),0);
fillchar(tmax,sizeof(tmax),0);
qmax[0]:=maxlongint;
qmin[0]:=-maxlongint;
lmax:=-n+1; rmax:=0;
lmin:=-n+1; rmin:=0;
end;
begin
readln(a,b,n);
for i:=1 to a do
begin
ql;
for j:=1 to b do
begin
read(x);
ins_max(x);
ins_min(x);
if j>=n then
begin
maxh[i,j]:=qmax[lmax];
minh[i,j]:=qmin[lmin];
end;
end;
readln;
end;
ans:=maxlongint;
for i:=n to b do
begin
ql;
for j:=1 to a do
begin
ins_max(maxh[j,i]);
ins_min(minh[j,i]);
if j>=n then
begin
maxn[j,i]:=qmax[lmax];
mini[j,i]:=qmin[lmin];
if maxn[j,i]-mini[j,i]<ans then ans:=maxn[j,i]-mini[j,i];
end;
end;
end;
write(ans);
end.