zoukankan      html  css  js  c++  java
  • bzoj 1047 理想的正方形

    题目大意:
    有一个a*b的矩阵,求所有矩阵内n*n的子矩阵内最大值与最小值之差的最小值

    思路:

    根据可以看出这是一道裸的单调队列。

    具体来说,就是用单调队列先维护出每行每个点左侧n个点以内的最大值,记为 t 数组。外层循环为a,内层为b

    然后再用单调队列维护每个点上方n个点以内的 t 数组的最大值,这样通过单调队列就能求出以每个点为右下角的子矩阵的最大值

    然后求每个点为右下角的子矩阵的最小值,方法同上

    就是这样

    #include<iostream>
    #include<cstdio>
    #include<cmath>
    #include<algorithm>
    #include<cstring>
    #include<cstdlib>
    #include<queue>
    #include<vector>
    #include<set>
    #include<stack>
    #define inf 2147483611
    #define ll long long
    #define MAXN 1010
    using namespace std;
    inline int read()
    {
        int x=0,f=1;
        char ch;ch=getchar();
        while(!isdigit(ch)) {if(ch=='-') f=-1;ch=getchar();}
        while(isdigit(ch)) {x=x*10+ch-'0';ch=getchar();}
        return x*f;
    }
    int n,a,b,head,tail;
    struct data
    {
        int pos,val;
    }q[MAXN];
    int map[MAXN][MAXN],t[MAXN][MAXN],maxa[MAXN][MAXN],mina[MAXN][MAXN];
    int main()
    {
        a=read(),b=read(),n=read();
        for(int i=1;i<=a;i++)
            for(int j=1;j<=b;j++)
                map[i][j]=read();
        for(int i=1;i<=a;i++)
        {
            head=1,tail=0;
            for(int j=1;j<=b;j++)
            {
                while(head<=tail&&q[tail].val<=map[i][j]) tail--;
                while(head<=tail&&q[head].pos<=j-n) head++;
                q[++tail].val=map[i][j],q[tail].pos=j;
                t[i][j]=q[head].val;
            }
        }
        for(int j=1;j<=b;j++)
        {
            head=1,tail=0;
            for(int i=1;i<=a;i++)
            {
                while(head<=tail&&q[tail].val<=t[i][j]) tail--;
                while(head<=tail&&q[head].pos<=i-n) head++;
                q[++tail].val=t[i][j],q[tail].pos=i;
                maxa[i][j]=q[head].val;
            }
        }
        for(int i=1;i<=a;i++)
        {
            head=1,tail=0;
            for(int j=1;j<=b;j++)
            {
                while(head<=tail&&q[tail].val>=map[i][j]) tail--;
                while(head<=tail&&q[head].pos<=j-n) head++;
                q[++tail].val=map[i][j],q[tail].pos=j;
                t[i][j]=q[head].val;
            }
        }
        for(int j=1;j<=b;j++)
        {
            head=1,tail=0;
            for(int i=1;i<=a;i++)
            {
                while(head<=tail&&q[tail].val>=t[i][j]) tail--;
                while(head<=tail&&q[head].pos<=i-n) head++;
                q[++tail].val=t[i][j],q[tail].pos=i;
                mina[i][j]=q[head].val;
            }
        }
        int ans=inf;
        for(int i=n;i<=a;i++) 
            for(int j=n;j<=b;j++) 
            ans=min(ans,maxa[i][j]-mina[i][j]);
        printf("%d",ans);
    }
    View Code
  • 相关阅读:
    ORM版,学生信息管理单表查询..
    回顾
    连接不上数据库
    CI缓存文件的处理和显示 研究
    php的两个符号@和&---php总会要知道的系列
    form 表单
    CI 目录下放置index.html,防止直接访问
    程序员必须知道的10大基础实用算法及其讲解
    memached 服务器lru算法
    centos 5.5 安装 lnmp
  • 原文地址:https://www.cnblogs.com/yyc-jack-0920/p/7570201.html
Copyright © 2011-2022 走看看