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.
原文地址:https://www.cnblogs.com/BLADEVIL/p/3511717.html