luogu P2216 [HAOI2007] ideal square solving report

The meaning of problems: there is a matrix of integers a * b, and you find out a current n * n square region, so that the difference between the minimum number of all the regions of maximum and minimum values.

 

Data Scale:

(1) number of all the matrix does not exceed 1,000,000,000

(2) 20% of the data 2 <= a, b <= 100, n <= a, n <= b, n <= 10

(3) 100% Data 2 <= a, b <= 1000, n <= a, n <= b, n <= 100

-------------------------------------------------- I was the dividing line ------------------------------ ---------------- --------------------------

Solution: For 20% of the data, the simple approach is O (A * B) enumerated each side length of rectangular N, then O (N ^ 2) determine the maximum and minimum rectangular, i.e. taking the difference minimum It can be the total time complexity O (A * B * N ^ 2).

Since the enumeration rectangle A * B is a minimum limit, can not be re-optimization, so we consider the optimization of most value N ^ 2 process.

Meaning of the questions, know that this problem is usually routine pretreatment.

In respect to (i, j) is the top left corner of the rectangle length K, we obviously have the following recursive formula:

Max(i,j,k) = max{Max(i,j,k), Max(i-1,j-1,k-1),Max(i,j-1,k-1), Max(i-1,j,k-1) }

The minimum value of empathy.

Due to space constraints, the size of the super-array memory limit, so we use the scroll array optimization, a dimension K is removed, the first pre-side length of the square 1, k-1 times and then recursion matrix, the resulting data is certainly k is the size of the rectangle side length, the total time complexity of O (a * B * N) , the desired score 50 points.

See the specific process of code implementation:

#include<bits/stdc++.h>

#define ll long long
#define mp make_pair
#define rep(i, a, b) for(int i = (a);i <= (b);++i)
#define per(i, a, b) for(int i = (a);i >= (b);--i)

using namespace std;

typedef pair<int, int> pii;
typedef double db;
const int N = 1e6 + 50;
int a, b, n, Map[1010][1010];
int Max[1010][1010], Min[1010][1010];
int ans = 1e9;
inline int read(){
    int x = 0, f = 1;
    char ch = getchar();
    while(ch < '0' || ch > '9'){if(ch == '-') f = -1; ch = getchar();}
    while(ch >='0' && ch <='9'){x = (x<<3)+(x<<1)+(ch^48); ch = getchar();}
    return x*f;
}
void init(){
    a = read(); b = read(); n = read();
    rep(i, 1, a) rep(j, 1, b){    
        Map[i][j] = read();
        Max[i][j] = Min[i][j] = Map[i][j];
    }
    rep(k, 2, n) per(i, a, k) per(j, b, k){
        Max[i][j] = max(max(Max[i-1][j-1], max(Max[i][j-1], Max[i-1][j])), Map[i][j]);
        Min[i][j] = min(min(Min[i-1][j-1], min(Min[i][j-1], Min[i-1][j])), Map[i][j]);
    }
}
void work(){
    rep(i, n, a) rep(j, n, b) ans = min(ans, Max[i][j] - Min[i][j]);
    printf("%d\n", ans);
}
int main(){
    init();
    work();
    return 0;
}
View Code

Since O (A * B * N) time complexity and are not good enough, need to be optimized pretreated complexity has reached the lower limit, so we need the change to the formula.

Max(i,j,k) = max{Max(i,j,k), Max(i+2^(k-1),j+2^(k-1),k-1),Max(i,j+2^(k-1),k-1), Max(i+2^(k-1),j,k-1)) }

I.e. multiplication method and found that this is a two-dimensional table ST, to pretreatment, the total time complexity is O (A * BlogN).

See the specific process of code implementation:

#include<bits/stdc++.h>

#define ll long long
#define mp make_pair
#define rep(i, a, b) for(int i = (a);i <= (b);++i)
#define per(i, a, b) for(int i = (a);i >= (b);--i)

using namespace std;

typedef pair<int, int> pii;
typedef double db;
const int N = 1e6 + 50;
int a, b, n, Map[1010][1010];
int Max[1010][1010], Min[1010][1010];
int ans = 1e9;
inline int read(){
    int x = 0, f = 1;
    char ch = getchar();
    while(ch < '0' || ch > '9'){if(ch == '-') f = -1; ch = getchar();}
    while(ch >='0' && ch <='9'){x = (x<<3)+(x<<1)+(ch^48); ch = getchar();}
    return x*f;
}
int ask_max(int l, int r){
    int k = log2(n);
    return max(Max[l][r], max(Max[l + n - (1<<k)][r + n - (1<<k)], max(Max[l + n - (1<<k)][r], Max[l][r + n - (1<<k)])));
}
int ask_min(int l, int r){
    int k = log2(n);
    return min(Min[l][r], min(Min[l + n - (1<<k)][r + n - (1<<k)], min(Min[l + n - (1<<k)][r], Min[l][r + n - (1<<k)])));
}
void init(){
    a = read(); b = read(); n = read();
    rep(i, 1, a) rep(j, 1, b){    
        Map[i][j] = read();
        Max[i][j] = Min[i][j] = Map[i][j];
    }
    int t = log2(n);
    rep(k, 0, t-1) rep(i, 1, a - (1<<k)) rep(j, 1, b - (1<<k)){
        Max[i][j] = max(Max[i][j], max(Max[i + (1<<k)][j + (1<<k)], max(Max[i + (1<<k)][j], Max[i][j + (1<<k)])));
        Min[i][j] = min(Min[i][j], min(Min[i + (1<<k)][j + (1<<k)], min(Min[i + (1<<k)][j], Min[i][j + (1<<k)])));
    }
}
void work(){
    rep(i, 1, a-n+1) rep(j, 1, b-n+1){
        ans = min(ans, ask_max(i, j) - ask_min(i, j));
    }
    printf("%d\n", ans);
}
int main(){
    init();
    work();
    return 0;
}
View Code

 

Guess you like

Origin www.cnblogs.com/smilke/p/11569612.html