zoukankan      html  css  js  c++  java
  • 理想的正方形 HAOI2007(二维RMQ)

    理想的正方形

     

    省队选拔赛河南

     时间限制: 1 s
     空间限制: 256000 KB
     题目等级 : 大师 Master
     
     
     
    题目描述 Description

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

    输入描述 Input Description

        第一行为3个整数,分别表示a,b,n的值

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

    输出描述 Output Description

     仅一个整数,为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

    数据范围及提示 Data Size & Hint

    (1)矩阵中的所有数都不超过1,000,000,000

    (2)20%的数据2<=a,b<=100,n<=a,n<=b,n<=10

    (3)100%的数据2<=a,b<=1500,n<=a,n<=b,n<=100

    /*
    嗯,脑补二维RMQ fail,挂成暴力分。
    一维是维护一个区间,二维是维护一个矩阵。
    由于这个题是小正方形,三维数组即可。二维RMQ略麻烦... 
    */
    #include<iostream>
    #include<cstdio>
    #include<cstring>
    #include<cmath>
    #include<cstdlib>
    
    #define x2 x1+n-1-(1<<m)+1
    #define y2 y1+n-1-(1<<m)+1
    
    using namespace std;
    void read(int &x)
    {
        int f=1;x=0;char c=getchar();
        while(!isdigit(c)){if(c=='-')f=-1;c=getchar();}
        while(isdigit(c)){x=(x<<3)+(x<<1)+c-'0';c=getchar();}
        x*=f;
    }
    
    void out(int x)
    {
        if(!x){putchar('0');return;}
        if(x<0){x=~x+1;putchar('-');}
        char c[30]= {0};
        while(x)c[++c[0]]=x%10+48,x/=10;
        while(c[0])putchar(c[c[0]--]);
    }
    const int inf=1e3+29;
    int i,j,k,m;
    int g[inf][inf][12];
    int f[inf][inf][12];
    int x,y,n;
    int ans=0x7fffffff;
    
    int query(int x1,int y1)
    {
        int maxn=0,minn=0x7fffffff;
        maxn=max(f[x1][y1][m],f[x2][y2][m]);
        maxn=max(maxn,f[x1][y2][m]);
        maxn=max(maxn,f[x2][y1][m]);
        minn=min(g[x1][y1][m],g[x2][y2][m]);
        minn=min(minn,g[x1][y2][m]);
        minn=min(minn,g[x2][y1][m]);
        return maxn-minn;
    }
    
    int main()
    {
        read(y);read(x);
        read(n);m=log(n)/log(2);
        for(i=1; i<=y; i++)
          for(j=1; j<=x; j++)
            {
                read(f[j][i][0]);
                g[j][i][0]=f[j][i][0];
            }
        for(k=1; k<=12; k++)
          for(i=1; i+(1<<k)-1<=x; i++)
            for(j=1; j+(1<<k)-1<=y; j++)
            {
                f[i][j][k]=max(f[i][j][k-1],f[i+(1<<(k-1))][j+(1<<(k-1))][k-1]);
                f[i][j][k]=max(f[i][j][k],f[i+(1<<(k-1))][j][k-1]);
                f[i][j][k]=max(f[i][j][k],f[i][j+(1<<(k-1))][k-1]);
                g[i][j][k]=min(g[i][j][k-1],g[i+(1<<(k-1))][j+(1<<(k-1))][k-1]);
                g[i][j][k]=min(g[i][j][k],g[i+(1<<(k-1))][j][k-1]);
                g[i][j][k]=min(g[i][j][k],g[i][j+(1<<(k-1))][k-1]);
            }
        for(i=1; i+n-1<=x; i++)
          for(j=1; j+n-1<=y; j++)
            ans=min(ans,query(i,j));
        out(ans);
        return 0;
    }
    折花枝,恨花枝,准拟花开人共卮,开时人去时。 怕相思,已相思,轮到相思没处辞,眉间露一丝。
  • 相关阅读:
    Leetcode 191.位1的个数 By Python
    反向传播的推导
    Leetcode 268.缺失数字 By Python
    Leetcode 326.3的幂 By Python
    Leetcode 28.实现strStr() By Python
    Leetcode 7.反转整数 By Python
    Leetcode 125.验证回文串 By Python
    Leetcode 1.两数之和 By Python
    Hdoj 1008.Elevator 题解
    TZOJ 车辆拥挤相互往里走
  • 原文地址:https://www.cnblogs.com/L-Memory/p/7719132.html
Copyright © 2011-2022 走看看