Luo Gu P2216 [HAOI2007] ideal square
Description
- A has a matrix composed of integer b, from which you now find an n square region of n so as to minimize the difference in the number of all the regions of maximum and minimum values.
Input
The first behavior three integers, represent the values a, b, n of
The second line to the first line of each conduct a + 1 b non-negative integer, the number of the corresponding position in the matrix indicates. Each line separated by a space between adjacent two numbers.
Output
- Only an integer, a is all "n matrix B minimum difference between the maximum and the minimum integer n integer square region," the.
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
answer:
- Monotone queue.
- A situation got out and comfortable.
- For obtaining a maximum of n * n rectangle may be thought of as the maximum value and the maximum value of each row in the n-th row. The maximum value of each row how demand? Segment tree, ST tables are OK. But is it better monotone queue?
- So the first queue determined monotonous point (i, j) is the i-th row j - n + 1 maximum / minimum value of the lattice j ~ .
- So for a rectangle we just need to enumerate n times you can get the maximum / minimum value of.
- However, you draw range n * n rectangle marquee with pen and paper. Can be found in each rectangle is the whole move down a grid. So this is a monotonous queue Yeah. But this is monotonous queue element to point (i, j) is the i-th row j - n + 1 ~ maximum / minimum value j of the trellis .
- Complexity is about O (2ab) = O (n ^ 2 scale).
- Oh, I get lazy with STL, a huge constant. Not open O2 90pts, open the O2 can A.
#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;
}