【HAOI 2007】理想正方形

  昨晚眼看宿舍就要熄灯锁门了,赶紧赶紧,终于把这个程序搞出来了……

  就是单调队列。先按行维护每行每段的最大值(max[][])和最小值(min[][]),然后再按列将处理好的max[][]和min[][]维护最大值(ans_max[][])和最小值(ans_min[][]),最后枚举一下正方形的左上方坐标更新就ok了……

  挺绕口的……看程序吧

var q:array[0..10000]of longint;

    max,min,ans_max,ans_min,w:Array[1..1000,1..1000]of longint;

    n,m,k,i,j,head,tail,ans:longint;



function cmp(a,b:longint):longint;

begin

     if a<b then cmp:=a

        else cmp:=b;

end;



begin

     readln(n,m,k);

     for i:=1 to n do

         for j:=1 to m do read(w[i,j]);



     for i:=1 to n do

         begin

              fillchar(q,sizeof(q),0);

              head:=1;tail:=0;

              for j:=1 to k-1 do

                  begin

                       while (head<=tail)and(w[i,q[tail]]<w[i,j]) do dec(tail);

                       inc(tail);q[tail]:=j;

                  end;

              for j:=k to m do

                  begin

                       while (head<=tail)and(w[i,q[tail]]<w[i,j]) do dec(tail);

                       inc(tail);q[tail]:=j;

                       while q[head]<j-k+1 do inc(head);

                       max[i,j-k+1]:=w[i,q[head]];

                  end;

         end;



     for i:=1 to n do

         begin

              fillchar(q,sizeof(q),0);

              head:=1;tail:=0;

              for j:=1 to k-1 do

                  begin

                       while (head<=tail)and(w[i,q[tail]]>w[i,j]) do dec(tail);

                       inc(tail);q[tail]:=j;

                  end;

              for j:=k to m do

                  begin

                       while (head<=tail)and(w[i,q[tail]]>w[i,j]) do dec(tail);

                       inc(tail);q[tail]:=j;

                       while q[head]<j-k+1 do inc(head);

                       min[i,j-k+1]:=w[i,q[head]];

                  end;

         end;



     for j:=1 to m-k+1 do

         begin

              fillchar(q,sizeof(q),0);

              head:=1;tail:=0;

              for i:=1 to k-1 do

                  begin

                       while (head<=tail)and(max[i,j]>max[q[tail],j]) do dec(tail);

                       inc(tail);q[tail]:=i;

                  end;

              for i:=k to n do

                  begin

                       while (head<=tail)and(max[i,j]>max[q[tail],j]) do dec(tail);

                       inc(tail);q[tail]:=i;

                       while q[head]<i-k+1 do inc(head);

                       ans_max[i-k+1,j]:=max[q[head],j];

                  end;



              fillchar(q,sizeof(q),0);

              head:=1;tail:=0;

              for i:=1 to k-1 do

                  begin

                       while (head<=tail)and(min[i,j]<min[q[tail],j]) do dec(tail);

                       inc(tail);q[tail]:=i;

                  end;

              for i:=k to n do

                  begin

                       while (head<=tail)and(min[i,j]<min[q[tail],j]) do dec(tail);

                       inc(tail);q[tail]:=i;

                       while q[head]<i-k+1 do inc(head);

                       ans_min[i-k+1,j]:=min[q[head],j];

                  end;

         end;



     ans:=maxlongint;

     for i:=1 to n-k+1 do

         for j:=1 to m-k+1 do

             ans:=cmp(ans,ans_max[i,j]-ans_min[i,j]);

     writeln(ans);

end.     

你可能感兴趣的:(2007)