Dancepted

Dancing Acceped!

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

 

posted on 2018-10-30 15:44  Danceped  阅读(217)  评论(0编辑  收藏  举报

导航