• P2216 [HAOI2007]理想的正方形(dp+单调队列优化)


    题目链接:传送门

    题目:

    题目描述
    
    有一个a*b的整数组成的矩阵,现请你从中找出一个n*n的正方形区域,使得该区域所有数中的最大值和最小值的差最小。
    输入输出格式
    输入格式:
    
    第一行为3个整数,分别表示a,b,n的值
    
    第二行至第a+1行每行为b个非负整数,表示矩阵中相应位置上的数。每行相邻两数之间用一空格分隔。
    
    输出格式:
    
    仅一个整数,为a*b矩阵中所有“n*n正方形区域中的最大整数和最小整数的差值”的最小值。
    
    输入输出样例
    输入样例#15 4 2
    1 2 5 6
    0 17 16 0
    16 17 2 1
    2 10 2 1
    1 2 2 2
    
    输出样例#11
    
    说明
    
    问题规模
    
    (1)矩阵中的所有数都不超过1,000,000,000220%的数据2<=a,b<=100,n<=a,n<=b,n<=103100%的数据2<=a,b<=1000,n<=a,n<=b,n<=100
    View Code

    思路:

    用2*b个单调队列维护:

      每长度为n的最大值和最小值;

    再用2个单调队列维护:

      更新到当前为止,行数为n的最大值的最大值,和最小值的最小值。

    #include <bits/stdc++.h>
    
    using namespace std;
    const int MAX_N = 1e3 + 5;
    const int INF = 0x3f3f3f3f;
    
    struct Node{
        int val, ind;
        Node(int v = 0, int i = 0) : val(v), ind(i) {}
    }querow[MAX_N], quecol[MAX_N][MAX_N], querow2[MAX_N], quecol2[MAX_N][MAX_N];
    
    int a, b, n;
    int headrow, tailrow, headcol[MAX_N], tailcol[MAX_N];
    int headrow2, tailrow2, headcol2[MAX_N], tailcol2[MAX_N];
    int mat[MAX_N][MAX_N];
    
    int main()
    {
        cin >> a >> b >> n;
        int ans = INF;
        for (int i = 1; i <= a; i++)
            for (int j = 1; j <= b; j++)
                scanf("%d", &mat[i][j]);
        for (int i = 1; i <= a; i++)
            headcol[i] = 1, tailcol[i] = 0, headcol2[i] = 1, tailcol2[i] = 0;
        for (int i = 1; i <= a; i++) {
            headrow = headrow2 = 1;
            tailrow = tailrow2 = 0;
            for (int j = 1; j <= b; j++) {
                while (headcol[j] <= tailcol[j] && quecol[j][tailcol[j]].val <= mat[i][j])
                    tailcol[j]--;
                quecol[j][++tailcol[j]] = Node(mat[i][j], i);
                while (headcol[j] <= tailcol[j] && quecol[j][headcol[j]].ind <= i-n)
                    headcol[j]++;
                Node cur = quecol[j][headcol[j]];
                while (headrow <= tailrow && querow[tailrow].val <= cur.val)
                    tailrow--;
                querow[++tailrow] = Node(cur.val, j);
                while (headrow <= tailrow && querow[headrow].ind <= j-n)
                    headrow++;
                Node _max = querow[headrow];
    
                while (headcol2[j] <= tailcol2[j] && quecol2[j][tailcol2[j]].val >= mat[i][j])
                    tailcol2[j]--;
                quecol2[j][++tailcol2[j]] = Node(mat[i][j], i);
                while (headcol2[j] <= tailcol2[j] && quecol2[j][headcol2[j]].ind <= i-n)
                    headcol2[j]++;
                Node cur2 = quecol2[j][headcol2[j]];
                while (headrow2 <= tailrow2 && querow2[tailrow2].val >= cur2.val)
                    tailrow2--;
                querow2[++tailrow2] = Node(cur2.val, j);
                while (headrow2 <= tailrow2 && querow2[headrow2].ind <= j-n)
                    headrow2++;
                Node _min = querow2[headrow2];
                if (i >= n && j >= n)
                    ans = min(ans, _max.val - _min.val);
            }
        }
        cout << ans << endl;
        return 0;
    }
    View Code
  • 相关阅读:
    对Java总体上的认识
    HTML+CSS学习情况
    读过的书籍
    FSCapture[个人认为最好的截图工具]
    会使用的软件
    深入理解Java中的引用的含义与原理
    从头开始学JavaScript (三)——数据类型
    从头开始学JavaScript (二)——变量及其作用域
    从头开始学JavaScript(一)——基础中的基础
    【Head First Javascript】学习笔记0——自己制作chm参考手册素材
  • 原文地址:https://www.cnblogs.com/Lubixiaosi-Zhaocao/p/9877220.html
Copyright © 2020-2023  润新知