zoukankan      html  css  js  c++  java
  • BZOJ 1047: [HAOI2007]理想的正方形

    好久沒更新過了 T_T,恰好BZOJ到達了100題,寫下這篇水的題解。。。

    1047: [HAOI2007]理想的正方形

    Time Limit: 10 Sec  Memory Limit: 162 MB
    Submit: 860  Solved: 418
    [Submit][Status][Discuss]

    Description

    有一个a*b的整数组成的矩阵,现请你从中找出一个n*n的正方形区域,使得该区域所有数中的最大值和最小值的差最小。

    Input

    第一行为3个整数,分别表示a,b,n的值 第二行至第a+1行每行为b个非负整数,表示矩阵中相应位置上的数。每行相邻两数之间用一空格分隔。

    Output

    仅一个整数,为a*b矩阵中所有“n*n正方形区域中的最大整数和最小整数的差值”的最小值。

    Sample Input

    5 4 2
    1 2 5 6
    0 17 16 0
    16 17 2 1
    2 10 2 1
    1 2 2 2

    Sample Output

    1
    问题规模
    (1)矩阵中的所有数都不超过1,000,000,000
    (2)20%的数据2<=a,b<=100,n<=a,n<=b,n<=10
    (3)100%的数据2<=a,b<=1000,n<=a,n<=b,n<=100

    HINT

     

    Source

     
    [Submit][Status][Discuss]

    分析:
    二維單調隊列。
    1.先對行進行單調隊列的操作,記錄max[i][j],min[i][j],表示從i-d+1到i行的最值。
    2.對於每列來說,我們同樣進行單調隊列操作,然後統計更新答案

    /*
    
    題目:
        有一个a*b的整数组成的矩阵,现请你从中找出一个n*n的正方形区域,
        使得该区域所有数中的最大值和最小值的差最小。
    分析:
        二維單調隊列。
        1.先對行進行單調隊列的操作,記錄max[i][j],min[i][j],表示從i-d+1到i行的最值。
        2.對於每列來說,我們同樣進行單調隊列操作,然後統計更新答案
    
    */
    #include <cstdio>
    #include <cstring>
    #include <iostream>
    #include <algorithm>
    
    using namespace std;
    
    typedef long long ll;
    typedef unsigned long long ull;
    
    #define lx(x) (x<<1)
    #define rx(x) (x<<1|1)
    #define debug puts("here")
    #define rep(i,n) for(int i=0;i<n;i++)
    #define rep1(i,n) for(int i=1;i<=n;i++)
    #define REP(i,a,b) for(int i=a;i<=b;i++)
    #define foreach(i,vec) for(unsigned i=0;i<vec.size();i++)
    #define pb push_back
    #define RD(n) scanf("%d",&n)
    #define RD2(x,y) scanf("%d%d",&x,&y)
    #define RD3(x,y,z) scanf("%d%d%d",&x,&y,&z)
    #define RD4(x,y,z,w) scanf("%d%d%d%d",&x,&y,&z,&w)
    
    /******** program ********************/
    
    const int MAXN = 1005;
    const int INF = 2e9;
    
    int ax[MAXN][MAXN],bn[MAXN][MAXN];
    int map[MAXN][MAXN],n,m,d;
    
    struct node{
        int id,val;
    }qmax[MAXN],qmin[MAXN];
    
    void init(){ // 預處理,計算出max[i][j],min[i][j]
        rep1(j,m){
            int t1 = 0,t2 = 0,h1 = 0,h2 = 0;
            rep1(i,n){
                // 計算max的單調隊列
                while(h1<t1&&i-qmax[h1+1].id>=d) // 越界
                    h1 ++;
                while(h1<t1&&qmax[t1].val<=map[i][j]) // 維護的是單調遞減的數列
                    t1 --;
                qmax[++t1].val = map[i][j];
                qmax[t1].id = i;
                if(i<d)
                    ax[i][j] = INF;
                else
                    ax[i][j] = qmax[h1+1].val;
    
                // 計算min的單調隊列
                while(h2<t2&&i-qmin[h2+1].id>=d) // 越界
                    h2 ++;
                while(h2<t2&&qmin[t2].val>=map[i][j]) // 維護的是單調遞增的數列
                    t2 --;
                qmin[++t2].val = map[i][j];
                qmin[t2].id = i;
                if(i<d)
                    bn[i][j] = 0;
                else
                    bn[i][j] = qmin[h2+1].val;
            }
        }
    }
    
    void solve(){ // 在max以及min數組上面進行行的單調隊列操作。
        int ans = INF;
        for(int i=1;i<=n;i++){
            int h1 = 0,h2 = 0,t1 = 0,t2 = 0;
            for(int j=1;j<=m;j++){
                // 行的max
                while(h1<t1&&j-qmax[h1+1].id>=d)
                    h1 ++;
                while(h1<t1&&qmax[t1].val<=ax[i][j])
                    t1 --;
                qmax[++t1].val = ax[i][j];
                qmax[t1].id = j;
    
                // 行的min
                while(h2<t2&&j-qmin[h2+1].id>=d)
                    h2 ++;
                while(h2<t2&&qmin[t2].val>=bn[i][j])
                    t2 --;
                qmin[++t2].val = bn[i][j];
                qmin[t2].id = j;
    
                if(i>=d&&j>=d)
                    ans = min(ans,qmax[h1+1].val-qmin[h2+1].val);
            }
        }
        cout<<ans<<endl;
    }
    
    int main(){
    
    #ifndef ONLINE_JUDGE
    	freopen("sum.in","r",stdin);
    	//freopen("sum.out","w",stdout);
    #endif
    
        while(~RD3(n,m,d)){
            rep1(i,n)
                rep1(j,m)
                    RD(map[i][j]);
            init();
            solve();
        }
    
    	return 0;
    }
    

      

  • 相关阅读:
    jq获取滚动条高度
    用jq实现简单的tab选项卡
    bootstrap基础css样式1
    c3中的弹性盒子
    第一天注册
    Windows平台下结合 tortoiseSVN 和 VisualSVN Server 搭建SVN服务器并实现 web 站点同步
    【转载】IIS出现“HTTP 错误 500.0,C:phpphp-cgi.exe
    【转载】PHP5.3 配置文件php.ini-development和php.ini-production的区别
    解决 Composer-Setup.exe 安装过程中的报错
    IIS配置页面重写(配合插件url-rewrite2去除页面后缀名)
  • 原文地址:https://www.cnblogs.com/yejinru/p/3010184.html
Copyright © 2011-2022 走看看