• bzoj1047-理想的正方形(二维单调队列)


    题意: 给一个矩阵,给出行列和每个数,再给出一个N,求出所有N*N的子矩阵中最大值最小值之差的最小值
    解析: 暴力枚举肯定不行,这题可以用二维单调队列做,把同一行的连续N个点缩成一个点保存最大最小值预处理
    ,用单调队列即可实现,再对整个矩阵进行枚举,再用一次单调队列。

    代码

    #include<cstdio>
    #include<cstring>
    #include<algorithm>
    #include<vector>
    #include<cmath>
    using namespace std;
    const int INF=1e9+7;
    const int maxn=1002;
    int row,col,N;
    int A[maxn][maxn];
    int Min[maxn][maxn],Max[maxn][maxn];
    int q1[maxn],q2[maxn];
    int f1,f2,r1,r2;
    void init() //预处理
    {
        for(int i=1;i<=row;i++)
        {
            f1=1,r1=0;
            f2=1,r2=0;
            for(int j=1;j<N;j++)
            {
                while(r1>=f1&&A[i][q1[r1]]>=A[i][j]) r1--;
                q1[++r1]=j;
                while(r2>=f2&&A[i][q2[r2]]<=A[i][j]) r2--;
                q2[++r2]=j;
            }
            for(int j=N;j<=col;j++)
            {
                while(r1>=f1&&A[i][q1[r1]]>=A[i][j]) r1--;
                q1[++r1]=j;
                while(q1[f1]+N<=j) f1++;
                Min[i][j-N+1]=A[i][q1[f1]]; //缩点后的最小值
    
                while(r2>=f2&&A[i][q2[r2]]<=A[i][j]) r2--;
                q2[++r2]=j;
                while(q2[f2]+N<=j) f2++;
                Max[i][j-N+1]=A[i][q2[f2]]; //缩点后的最大值
            }
        }
    }
    int solve()
    {
        int ret=INF;
        for(int j=1;j+N-1<=col;j++) //对同一列进行枚举
        {
            f1=1,r1=0;
            f2=1,r2=0;
            int minv=INF,maxv=-INF;
            for(int i=1;i<N;i++)
            {
                while(r1>=f1&&Min[q1[r1]][j]>=Min[i][j]) r1--;
                q1[++r1]=i;
                while(r2>=f2&&Max[q2[r2]][j]<=Max[i][j]) r2--;
                q2[++r2]=i;
            }
            for(int i=N;i<=row;i++)
            {
                while(r1>=f1&&Min[q1[r1]][j]>=Min[i][j]) r1--;
                q1[++r1]=i;
                while(q1[f1]+N<=i) f1++;
                minv=Min[q1[f1]][j];
                while(r2>=f2&&Max[q2[r2]][j]<=Max[i][j]) r2--;
                q2[++r2]=i;
                while(q2[f2]+N<=i) f2++;
                maxv=Max[q2[f2]][j];
                ret=min(ret,maxv-minv);
            }
        }
        return ret;
    }
    int main()
    {
        scanf("%d%d%d",&row,&col,&N);
        for(int i=1;i<=row;i++)
            for(int j=1;j<=col;j++) scanf("%d",&A[i][j]);
        init();
        printf("%d
    ",solve());
        return 0;
    }
    View Code
  • 相关阅读:
    Oracle ref cursor和sys_refcursor
    一些命令可以帮您了解Linux 操作系统用户信息
    Linux 6上使用UDEV绑定共享存储
    Oracle VirtualBox 问题汇总
    Linux 常用操作
    CentOS 7 运行级别切换
    Oracle 更新Opatch、打补丁
    django rest framework restful 规范
    CBV FBV rest framework
    CRM
  • 原文地址:https://www.cnblogs.com/wust-ouyangli/p/5809483.html
Copyright © 2020-2023  润新知