AcWing 1091. 理想的正方形 (求两次单调队列 )

2021-03-08 12:29:32 浏览数 (1)

这道题我们可以将每一行的滑动窗口求出来 然后统一放在窗口的最后一个位置 最后进行列的滑动窗口压缩 最大值最小值分别做一次 遍历一遍预处理出的最大值和最小值数组 更新答案即可

代码语言:javascript复制
#include<bits/stdc  .h>
using namespace std;
const int N=1010;
int n,m,k,a[N][N],ans_min[N][N],ans_max[N][N];
void getmin(int a[],int b[],int n){
    deque<int>q;
    for(int i=1;i<=n;i  ){
        if(!q.empty()&&i-q.front()>=k)q.pop_front();
        while(!q.empty()&&a[q.back()]>=a[i])q.pop_back();
        q.push_back(i);
        b[i]=a[q.front()];
    }
}
void getmax(int a[],int b[],int n){
    deque<int>q;
    for(int i=1;i<=n;i  ){
        if(!q.empty()&&i-q.front()>=k)q.pop_front();
        while(!q.empty()&&a[q.back()]<=a[i])q.pop_back();
        q.push_back(i);
        b[i]=a[q.front()];
    }
}
int main(){
    cin>>n>>m>>k;
    for(int i=1;i<=n;i  ){
        for(int j=1;j<=m;j  )scanf("%d",&a[i][j]);
    }
    for(int i=1;i<=n;i  ){
        getmin(a[i],ans_min[i],m),getmax(a[i],ans_max[i],m);
        /*for(int j=1;j<=m;j  ){
            cout<<ans_min[i][j]<<" ";
        }
        cout<<endl;*/
    }
    int ans=INT_MAX,tepa[N],tarb[N],tarc[N];
    for(int i=k;i<=m;i  ){
        for(int j=1;j<=n;j  ){
            tepa[j]=ans_min[j][i];
        }
        getmin(tepa,tarb,n);
        for(int j=1;j<=n;j  ){
            tepa[j]=ans_max[j][i];
        }
        getmax(tepa,tarc,n);
        for(int j=k;j<=n;j  )ans=min(ans,tarc[j]-tarb[j]);
    }
    cout<<ans<<endl;
}

0 人点赞