BZOJ 1047 理想的正方形

单调队列的基本应用。

#include<iostream>
#include<cstdio>
#include<cstring>
#include<algorithm>
#define maxn 1050
#define inf 2000000000
using namespace std;
int n,m,a,map[maxn][maxn],m1[maxn][maxn][3],m2[maxn][maxn][3],q1[maxn],q2[maxn],l1,r1,l2,r2,ans=inf;
void get_m1()
{
    for (int i=1;i<=n;i++)
    {
        l1=l2=1;r1=r2=0;
        for (int j=m;j>=1;j--)
        {
            while ((l1<=r1) && (q1[l1]>=j+a)) l1++;
            while ((l2<=r2) && (q2[l2]>=j+a)) l2++;
            while ((l1<=r1) && (map[i][j]>map[i][q1[r1]])) r1--;
            while ((l2<=r2) && (map[i][j]<map[i][q2[r2]])) r2--;
            q1[++r1]=j;q2[++r2]=j;
            m1[i][j][1]=map[i][q1[l1]];m1[i][j][2]=map[i][q2[l2]];
        }
    }
}
void get_m2()
{
    for (int i=1;i<=m;i++)
    {
        l1=l2=1;r1=r2=0;
        for (int j=n;j>=1;j--)
        {
            while ((l1<=r1) && (q1[l1]>=j+a)) l1++;
            while ((l2<=r2) && (q2[l2]>=j+a)) l2++;
            while ((l1<=r1) && (m1[j][i][1]>m1[q1[r1]][i][1])) r1--;
            while ((l2<=r2) && (m1[j][i][2]<m1[q2[r2]][i][2])) r2--;
            q1[++r1]=j;q2[++r2]=j;
            m2[j][i][1]=m1[q1[l1]][i][1];m2[j][i][2]=m1[q2[l2]][i][2];
        }
    }
}
int main()
{
    scanf("%d%d%d",&n,&m,&a);
    for (int i=1;i<=n;i++)
        for (int j=1;j<=m;j++)    
            scanf("%d",&map[i][j]);
    get_m1();
    get_m2();
    for (int i=1;i<=n-a+1;i++)
        for (int j=1;j<=m-a+1;j++)
            ans=min(ans,m2[i][j][1]-m2[i][j][2]);
    printf("%d
",ans);
    return 0;
}
原文地址:https://www.cnblogs.com/ziliuziliu/p/6046674.html