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

    题目描述

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

    输入输出格式

    输入格式:

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

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

    输出格式:

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

    输入输出样例

    输入样例#1:
    5 4 2
    1 2 5 6
    0 17 16 0
    16 17 2 1
    2 10 2 1
    1 2 2 2
    
    输出样例#1:
    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

    /*
    就是为了这个题目学的st表
    
    st表能够维护数列的某个地方往后2的整数次方的极值
    
    这个题目用st表来维护矩阵中某个元素往右下方二次方整数边长的矩阵元素的极值
    
    然后四块合并    O1 查询四块原理就和ST表一样了 
    */
    
    
    #include<cstdio>
    #include<algorithm>
    #include<iostream>
    #include<cmath>
    using namespace std;
    
    int maxx[1001][1001][13];
    int minn[1001][1001][13];
    int read()
    {
        int num = 0;
        char c = getchar();
        while(c > '9' || c < '0')c = getchar();
        while(c <= '9' && c >= '0')
        {
            num *= 10;
            num += c - '0';
            c = getchar();
         } 
         return num;
    }
    
    int n,m,k,p;
    int ans = 0x7fffffff;
    int main()
    {
        n = read();m = read();k = read();
        for(int i = 1;i <= n;i++)
            for(int j = 1;j <= m;j++)
                maxx[i][j][0] = minn[i][j][0] = read();
        p = log(k) / log(2);
        for(int i = 1;i <= 11;i++)
        {
            for(int j = 1;j + (1 << i) - 1 <= n;j++)
                for(int z = 1;z + (1 << i) - 1<= m;z++)
                {
                    maxx[j][z][i] = 
                    max(maxx[j][z][i - 1],
                    max(maxx[j][z + (1 << (i - 1))][i - 1],
                    max(maxx[j + (1 << (i - 1))][z + (1 << (i - 1))][i - 1],
                        maxx[j + (1 << (i - 1))][z][i - 1])));
                    
                    minn[j][z][i] = 
                    min(minn[j][z][i - 1],
                    min(minn[j][z + (1 << (i - 1))][i - 1],
                    min(minn[j + (1 << (i - 1))][z + (1 << (i - 1))][i - 1],
                        minn[j + (1 << (i - 1))][z][i - 1])));
                }
        }
        for(int x = 1;x + k - 1 <= n;x++)
            for(int y = 1;y + k - 1 <= m;y++)
            {
                    ans = min(ans,
                max(maxx[x][y][p],
                max(maxx[x][y + k - (1 << p)][p],
                max(maxx[x + k - (1 << p)][y][p],
                    maxx[x + k - (1 << p)][y + k - (1 << p)][p]))) -
                min(minn[x][y][p],
                min(minn[x][y + k - (1 << p)][p],
                min(minn[x + k - (1 << p)][y][p],
                    minn[x + k - (1 << p)][y + k - (1 << p)][p]))));
            }
        printf("%d",ans);
        return 0;
    } 
  • 相关阅读:
    转:BIOS的恢复技术之Top Swap的原理应用
    半硬化树脂PP的型号
    PADS常用画板过程
    ad2014注册出现:注册
    CPU处理多任务——中断与轮询方式比较
    PDS常用快捷键
    方法三破解:Excel工作表保护密码
    【Linux指标】内存篇
    mac apt-get--> Homebrew
    20180113Go匿名函数和闭包
  • 原文地址:https://www.cnblogs.com/luoyibujue/p/7663500.html
Copyright © 2011-2022 走看看