bzoj 1047 单调队列

首先将每一列压成一行,ans[i,j]代表[i,j]位及以上共n位的最大值,这个可以每一列用单调队列处理,然后对于每一行,类似于上述的处理,这样就可以得出以[i,j]为右下角的边长为n的矩阵的最大值。然后将所有值取相反数,再求一遍最大值,再取相反数,这样就可以得出最小值,然后扫一遍合法的点更新答案。

/**************************************************************

    Problem: 1047

    User: BLADEVIL

    Language: Pascal

    Result: Accepted

    Time:4192 ms

    Memory:24184 kb

****************************************************************/

 

//By BLADEVIL

var

    a, b, n                     :longint;

    map                         :array[0..1010,0..1010] of longint;

    ans                         :array[0..1010,0..1010,0..2] of longint;

    que                         :array[-1..200] of longint;

    max, min                    :array[0..1010,0..1010] of longint;

    print                       :longint;

     

procedure init;

var

    i, j                        :longint;

begin

    read(a,b,n);

    for i:=1 to a do

        for j:=1 to b do read(map[i,j]);

end;

 

procedure insert(x:longint);

begin

    if que[0]=que[-1] then

    begin

        inc(que[0]);

        que[que[0]]:=x;

    end else

    begin

        while (que[0]>que[-1]) and (que[que[0]]<x) do dec(que[0]);

        inc(que[0]);

        que[que[0]]:=x;

    end;

end;

 

procedure delete(x:longint);

begin

    if x=que[que[-1]+1] then inc(que[-1]);

end;

 

procedure make(x:longint);

var

    i, j, k                     :longint;

begin

    for j:=1 to b do

    begin

        fillchar(que,sizeof(que),0);

        for i:=1 to a do

        begin

            insert(map[i,j]);

            if i>n then delete(map[i-n,j]);

            ans[i,j,x]:=que[que[-1]+1];

        end;

    end;

    for i:=1 to a do

    begin

        fillchar(que,sizeof(que),0);

        for j:=1 to b do

        begin

            insert(ans[i,j,x]);

            if j>n then delete(ans[i,j-n,x]);

            ans[i,j,x xor 1]:=que[que[-1]+1];

        end;

    end;

end;

 

procedure main;

var

    i, j                        :longint;

begin

    make(0);

    for i:=1 to a do

        for j:=1 to b do max[i,j]:=ans[i,j,1];

    fillchar(ans,sizeof(ans),0);

    for i:=1 to a do

        for j:=1 to b do map[i,j]:=-map[i,j];

    make(0);

    for i:=1 to a do

        for j:=1 to b do min[i,j]:=-ans[i,j,1];

    print:=maxlongint;

    for i:=n to a do

        for j:=n to b do

        if max[i,j]-min[i,j]<print then print:=max[i,j]-min[i,j];

    writeln(print);

end;

 

begin

    init;

    main;

end.

 

你可能感兴趣的:(ZOJ)