BZOJ 1047 理想的正方形

可以先合一维再合一维

两个方向单调队列分别搞一下即可

蒟蒻我居然想不到单调队列

#include <cstdio>

const int MAXN=1011;
const int MAXM=1011;
const int INF=1034567890;

int N, M, K;
int Map[MAXN][MAXM], Temp[MAXN][MAXM], Max[MAXN][MAXM], Min[MAXN][MAXM];

int Q[MAXN+MAXM], Head, Tail;

int main(){
    
    scanf("%d%d%d", &N, &M, &K);
    for(int i=1;i<=N;++i)
        for(int j=1;j<=M;++j)
            scanf("%d", &Map[i][j]);
    
    for(int i=1;i<=N;++i){
        Head=1;Tail=1;
        for(int j=1;j<=M;++j){
            while(Head<Tail && Map[i][Q[Tail-1]]<=Map[i][j])    --Tail;
            Q[Tail++]=j;
            while(Q[Head]<=j-K) ++Head;
            Temp[i][j]=Map[i][Q[Head]];
        }
    }
    
    for(int j=1;j<=M;++j){
        Head=1;Tail=1;
        for(int i=1;i<=N;++i){
            while(Head<Tail && Temp[Q[Tail-1]][j]<=Temp[i][j])  --Tail;
            Q[Tail++]=i;
            while(Q[Head]<=i-K) ++Head;
            Max[i][j]=Temp[Q[Head]][j];
        }
    }
    
    for(int i=1;i<=N;++i){
        Head=1;Tail=1;
        for(int j=1;j<=M;++j){
            while(Head<Tail && Map[i][Q[Tail-1]]>=Map[i][j])    --Tail;
            Q[Tail++]=j;
            while(Q[Head]<=j-K) ++Head;
            Temp[i][j]=Map[i][Q[Head]];
        }
    }
    
    for(int j=1;j<=M;++j){
        Head=1;Tail=1;
        for(int i=1;i<=N;++i){
            while(Head<Tail && Temp[Q[Tail-1]][j]>=Temp[i][j])  --Tail;
            Q[Tail++]=i;
            while(Q[Head]<=i-K) ++Head;
            Min[i][j]=Temp[Q[Head]][j];
        }
    }
    
    for(int i=1;i<=N;++i)
        for(int j=1;j<=M;++j)
            Temp[i][j]=Max[i][j]-Min[i][j];
    
    int ANS=INF;
    
    for(int i=K;i<=N;++i)
        for(int j=K;j<=M;++j)
            if(Temp[i][j]<ANS)  ANS=Temp[i][j];
    
    printf("%d\n", ANS);
    
    return 0;
}

/*
5 4 2
1 2 5 6
0 17 16 0
16 17 2 1
2 10 2 1
1 2 2 2

1

*/

猜你喜欢

转载自www.cnblogs.com/Pickupwin/p/9170507.html
今日推荐