羅区P2216 [HAOI2007]理想の四角

羅区P2216 [HAOI2007]理想の四角

説明

  • Aが有する今N見つけ、そこから整数Bからなるマトリックス、最大値と最小値の全ての領域の数の差が最小となるようにn個の正方形領域。

入力

  • 最初の動作三つの整数、B、Nの値を表します

    各行動A + 1、B非負整数の最初の行の2行目には、マトリックス中の対応する位置の数を示しています。各ラインは、隣接する二つの数字の間のスペースで区切られました。

出力

  • 唯一の整数、aは「N行列Bの全て、最大及び最小の整数nは整数正方形領域間の最小差」。

サンプル入力

5 4 2

1 2 5 6

0 17 16 0

16 17 2 1

2 10 2 1

1 2 2 2

サンプル出力

1

ソリューション:

  • モノトーンキュー。
  • 状況が出て、快適。
  • N×n個の長方形の最大値を得るための最大値とn行目の各行の最大値と考えることができます。需要各行の方法最大値はありますか?セグメントツリーは、STテーブルはOKです。しかし、それはより良い単調キューのですか?
  • したがって、最初のキューは、単調な決定点(i、j)はi番目の行jである- N + 1つの最大/格子jの最小値〜
  • だから、長方形のために私達はちょうどあなたがの最大/最小値を得ることができますn回を列挙する必要があります。
  • ただし、ペンと紙との範囲のn * n個の矩形マーキーを描画します。各矩形で見つけることができますグリッドダウン全体の動きです。だから、これは単調なキューがそうです。しかし、これは単調キュー要素である点(i、j)がi番目の行j -でトレリスのN + 1〜最大/最小値j
  • 複雑さはO(2AB)= O(N ^ 2スケール)程度です。
  • ああ、私はSTL、巨大な定数と怠惰を得ます。することができますA. O2を開いて、O2 90ptsを開けません
#include <iostream>
#include <cstdio>
#include <queue>
#define N 1005
#define inf 0x7fffffff
using namespace std;

struct Node1
{
    int val, pos;
    friend bool operator < (Node1 x, Node1 y) {
        return x.val < y.val;
    }
};
struct Node2
{
    int val, pos;
    friend bool operator < (Node2 x, Node2 y) {
        return x.val > y.val;
    }
};
int n, m, len, ans = inf;
int Max[N][N], Min[N][N];

int read()
{
    int x = 0; char c = getchar();
    while(c < '0' || c > '9') c = getchar();
    while(c >= '0' && c <= '9') {x = x * 10 + c - '0'; c = getchar();}
    return x;
}

int main()
{
    cin >> n >> m >> len;
    for(int i = 1; i <= n; i++)
    {
        priority_queue<Node1> que1;
        priority_queue<Node2> que2;
        for(int j = 1; j < len; j++)
        {
            int x = read();
            que1.push((Node1){x, j});
            que2.push((Node2){x, j});
        }
        for(int j = len; j <= m; j++)
        {
            while(que1.size() && que1.top().pos <= j - len) que1.pop();
            while(que2.size() && que2.top().pos <= j - len) que2.pop();
            int x = read();
            que1.push((Node1){x, j});
            que2.push((Node2){x, j});
            Max[i][j] = que1.top().val;
            Min[i][j] = que2.top().val;
        }
    }
    for(int j = len; j <= m; j++)
    {
        priority_queue<Node1> que1;
        priority_queue<Node2> que2;
        for(int i = 1; i < len; i++)
        {
            int v1 = Max[i][j];
            int v2 = Min[i][j];
            que1.push((Node1){v1, i});
            que2.push((Node2){v2, i});
        }
        for(int i = len; i <= n; i++)
        {
            while(que1.size() && que1.top().pos <= i - len) que1.pop();
            while(que2.size() && que2.top().pos <= i - len) que2.pop();
            int v1 = Max[i][j];
            int v2 = Min[i][j];
            que1.push((Node1){v1, i});
            que2.push((Node2){v2, i});
            ans = min(ans, que1.top().val - que2.top().val);
        }
    }
    cout << ans;
    return 0;
}

おすすめ

転載: www.cnblogs.com/BigYellowDog/p/11514929.html