BZOJ1047

来源:互联网 发布:淘宝可以不交保证金吗 编辑:程序博客网 时间:2024/06/06 02:50

传送门:BZOJ1047

我们用f(i,j)表示第j列上区间[max(i-n+1,1),i]的最小值。
这一步的转移可以用单调队列来完成。
然后,我们用g(i,j)来表示以点(i,j)为右下角的边长为n的正方形中元素的最小值。
转移是:g(i,j)=min:f(i,j’),j’∈[max(j-n+1,1),j],于是它也可以用一个单调队列来优化。
注意细节。

代码上的小细节见下。

#include <cstdio>#include <cstdlib>#include <cmath>#include <cstring>#include <algorithm>#include <iostream>#include <queue>using namespace std;const int INF=0x3f3f3f3f;deque<int> Q;int f[1005][1005];int g[1005][1005];int r[1005][1005];int map[1005][1005];int a,b,n;void First_min(){    for(int i=1;i<=a;i++){        for(int j=1;j<=b;j++){            f[i][j]=map[i][j];            if(!Q.empty()){                f[i][j]=min(f[i][j],map[i][Q.front()]);                if(j-Q.front()+1>=n)                    Q.pop_front();            }            while(!Q.empty()&&map[i][Q.back()]>=map[i][j])                Q.pop_back();            Q.push_back(j);        }        while(!Q.empty())            Q.pop_back();    }    for(int j=1;j<=b;j++){        for(int i=1;i<=a;i++){            g[i][j]=f[i][j];            if(!Q.empty()){                g[i][j]=min(g[i][j],f[Q.front()][j]);                if(i-Q.front()+1>=n)                    Q.pop_front();            }            while(!Q.empty()&&f[Q.back()][j]>=f[i][j])                Q.pop_back();            Q.push_back(i);        }        while(!Q.empty())            Q.pop_back();    }}void First_max(){    for(int i=1;i<=a;i++){        for(int j=1;j<=b;j++){            f[i][j]=map[i][j];            if(!Q.empty()){                f[i][j]=max(f[i][j],map[i][Q.front()]);                //printf("%d %d %d\n",i,j,Q.front());                if(j-Q.front()+1>=n)                    Q.pop_front();            }            while(!Q.empty()&&map[i][Q.back()]<=map[i][j])                Q.pop_back();            Q.push_back(j);        }        while(!Q.empty())            Q.pop_back();    }    for(int j=1;j<=b;j++){        for(int i=1;i<=a;i++){            r[i][j]=f[i][j];            if(!Q.empty()){                r[i][j]=max(r[i][j],f[Q.front()][j]);                if(i-Q.front()+1>=n)                    Q.pop_front();            }            while(!Q.empty()&&f[Q.back()][j]<=f[i][j])                Q.pop_back();            Q.push_back(i);        }        while(!Q.empty())            Q.pop_back();    }}void Solve(){    int ans=INF;    for(int i=1;i<=a;i++)        for(int j=1;j<=b;j++)            if(i>=n&&j>=n)                ans=min(ans,r[i][j]-g[i][j]);    printf("%d\n",ans);}void Readdata(){    freopen("loli.in","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",&map[i][j]);}void Close(){    fclose(stdin);    fclose(stdout);}int main(){    Readdata();    First_min();    First_max();    Solve();    Close();    return 0;}
0 0
原创粉丝点击