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

    1047: [HAOI2007]理想的正方形

    Time Limit: 10 Sec  Memory Limit: 162 MB
    Submit: 3311  Solved: 1819
    [Submit][Status][Discuss]

    Description

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

    Input

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

    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
    分析:数据这么大,直接搜肯定是不行的.可以发现这道题就是滑动的窗口的二维版本,只不过要同时求出最大值和最小值罢了,那么就可以用单调队列来求.
    那么二维的单调队列该怎么写呢?其实对于一维转二维的问题,我们只需要先单独处理行或列,然后将处理好的看作是一个元素,然后转化为一维进行处理.
    在这里,我们先求出每一列的单调队列,用数组记录下以(i,j)为最下面的一个元素的长度为n的当前列的元素的最大值或最小值(有点绕),然后利用求出来的数组在每一行上求单调队列,最后统计出答案.
    #include <cstdio>
    #include <cstring>
    #include <iostream>
    #include <algorithm>
    
    const int inf = 1000000000;
    using namespace std;
    
    int a, b, n, map[1010][1010], q1[1010], q2[1010], num1[1010], num2[1010], maxx[1010][1010], minx[1010][1010], ans = inf;
    
    void solve1()
    {
        int l1, r1, l2, r2;
        for (int j = 1; j <= b; j++)
        {
            l1 = l2 = 1;
            r1 = r2 = 0;
            for (int i = 1; i <= a; i++)
            {
                //队列1
                while (l1 <= r1 && i - num1[l1] >= n)
                    l1++;
                while (l1 <= r1 && q1[r1] < map[i][j])
                    r1--;
                q1[++r1] = map[i][j];
                num1[r1] = i;
                //队列2
                while (l2 <= r2 && i - num2[l2] >= n)
                    l2++;
                while (l2 <= r2 && q2[r2] > map[i][j])
                    r2--;
                q2[++r2] = map[i][j];
                num2[r2] = i;
                if (i >= n)
                {
                    maxx[i][j] = q1[l1];
                    minx[i][j] = q2[l2];
                }
        
            }
        }
    }
    
    void solve2()
    {
        int l1, r1, l2, r2;
        for (int i = 1; i <= a; i++)
        {
            l1 = l2 = 1;
            r1 = r2 = 0;
            for (int j = 1; j <= b; j++)
            {
                while (l1 <= r1 && j - num1[l1] >= n)
                    l1++;
                while (l1 <= r1 && q1[r1] < maxx[i][j])
                    r1--;
                q1[++r1] = maxx[i][j];
                num1[r1] = j;
    
                while (l2 <= r2 && j - num2[l2] >= n)
                    l2++;
                while (l2 <= r2 && q2[r2] > minx[i][j])
                    r2--;
                q2[++r2] = minx[i][j];
                num2[r2] = j;
                if (i >= n && j >= n)
                    ans = min(ans, q1[l1] - q2[l2]);
            }
        }
    }
    
    int main()
    {
        scanf("%d%d%d", &a, &b, &n);
        for (int i = 1; i <= a;i++)
            for (int j = 1; j <= b; j++)
                scanf("%d", &map[i][j]);
        solve1();
        solve2();
        printf("%d", ans);
    
        return 0;
    }
  • 相关阅读:
    SDOI2008Cave 洞穴勘测
    使用Nginx反向代理和内容替换模块实现网页内容动态替换功能
    使用Nginx反向代理和内容替换模块实现网页内容动态替换功能
    Js 变量声明提升和函数声明提升
    Js 变量声明提升和函数声明提升
    Golang-filepath使用
    Golang-filepath使用
    44、File类简介
    44、File类简介
    div/dom元素拖拽缩放插件,纯js实现拖拽缩放,不依赖jQuery~
  • 原文地址:https://www.cnblogs.com/zbtrs/p/7008472.html
Copyright © 2011-2022 走看看