BZOJ 1047 单调队列求二维滑动窗口最值

来源:互联网 发布:qq空间解锁软件 编辑:程序博客网 时间:2024/06/05 18:43

先对每一行求出ci[i][j]表示从vij往后的n个数中最小的数。
然后用求出来的ci做列单调队列,最后求出的就是n*n的最值。

#include<iostream>#include<cstdio>#include<cstring>#include<algorithm>#define INF 1000000000using namespace std;const int maxn=2005;int a,b,n;int v[maxn][maxn],cx[maxn][maxn],ci[maxn][maxn],tx[maxn][maxn],ti[maxn][maxn];int mi[maxn],mx[maxn];void pre1(){    for(int i=1;i<=a;i++){        int l=1,r=0;        for(int j=1;j<=b+1;j++){            if(j>=n+1){                while(l<=r&&mx[l]<j-n){                    l++;                }                cx[i][j-n]=v[i][mx[l]];            }            while(l<=r&&v[i][mx[r]]<=v[i][j]){                r--;            }            mx[++r]=j;            }        l=1;r=0;        for(int j=1;j<=b+1;j++){            if(j>=n+1){                while(l<=r&&mi[l]<j-n){                    l++;                }                ci[i][j-n]=v[i][mi[l]];            }            while(l<=r&&v[i][mi[r]]>=v[i][j]){                r--;            }            mi[++r]=j;        }    }}void pre2(){    for(int j=1;j<=b;j++){        int l=1,r=0;        for(int i=1;i<=a+1;i++){            if(i>=n+1){                while(l<=r&&mx[l]<i-n){                    l++;                }                tx[i-n][j]=cx[mx[l]][j];            }            while(l<=r&&cx[mx[r]][j]<=cx[i][j]){                r--;            }            mx[++r]=i;        }        l=1,r=0;        for(int i=1;i<=a+1;i++){            if(i>=n+1){                while(l<=r&&mi[l]<i-n){                    l++;                }                ti[i-n][j]=ci[mi[l]][j];            }            while(l<=r&&ci[mi[r]][j]>=ci[i][j]){                r--;            }             mi[++r]=i;        }    }}int main(){    //freopen("in.txt","r",stdin);    scanf("%d%d%d",&a,&b,&n);    for(int i=1;i<=a;i++){        for(int j=1;j<=b;j++){            scanf("%d",&v[i][j]);        }    }    pre1();    pre2();    int ans=INF;    for(int i=1;i<=a-n+1;i++){        for(int j=1;j<=b-n+1;j++){            ans=min(ans,tx[i][j]-ti[i][j]);        }    }    printf("%d\n",ans);    return 0;}
0 0
原创粉丝点击