羅区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;
}