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.
(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
First, is st contemplated tabular form, followed by a three-dimensional expression, often coupled with the fast reader:
#include<cstdio> #include<cstdlib> #include<algorithm> using namespace std; int a,b,n; const int N=1003,M=103; int mn[N][N][M],mx[N][N][M]; inline int read() { int x=0;char c=getchar(); while(c<'0' || c>'9') c=getchar(); while(c>='0'&&c<='9') x=(x<<3)+(x<<1)+c-'0',c=getchar(); return x; } int main() { a=read(),b=read(),n=read(); for(int i=1;i<=a;i++) for(int j=1;j<=b;j++) mx[i][j][1]=mn[i][j][1]=read(); for(int i=2;i<=n;i++) For ( int sx = i + 1 ; sx; sx-- ) for ( int a = b + 1 ; and; sy-- ) { mn [sx] [and] [i] = min (min (mn [sx] [and] [i- 1 ], mn [sx + 1 ] [ 1 ] [i- 1 ]), min (mn [sx] [+ 1 ] [i- 1 ], mn [sx + 1 ], [ and] [i- 1 ])); mx, sx] [and] [i] = max (max (mx, sx] [and] [i- 1 ], mx, sx + 1 ] [ 1 ] [i- 1]), Max (mx, sx + 1 ] [i- 1 ], mx, sx + 1 ] [and] [i- 1 ])); } Int ans = 1 << 30 ; for ( int sx = a-n + 1 ; sx; sx-- ) for ( int a = b n + 1 ; and; sy-- ) ans = min (ans, mx, sx] [and] [n] - mn [sx] [and] [n]); printf ( " % d \ n " , ans); return 0 ; }
Then the results: 20> 20
Card often ineffective, it is estimated that the original code is too slow
Then pressing the minus one-dimensional solution to a problem ......
20-> 60, fantastic!
So minus one-dimensional likely to speed up large extent
#include<cstdio> #include<cstdlib> #include<algorithm> using namespace std; int a,b,n; const int N=1003,M=103; int mn[N][N],mx[N][N]; inline int read() { int x=0;char c=getchar(); while(c<'0' || c>'9') c=getchar(); while(c>='0'&&c<='9') x=(x<<3)+(x<<1)+c-'0',c=getchar(); return x; } int main() { a=read(),b=read(),n=read(); for(int i=1;i<=a;i++) for(int j=1;j<=b;j++) mx[i][j]=mn[i][j]=read(); for(int i=2;i<=n;i++) { intr1 = i + 1 ; for ( int sx = 1 ; sx <= r1; sx ++ ) { int R2 = b i + 1 ; for ( int = 1 ; and <= R2; and ++ ) { mn [sx] [and] = min (min (mn [sx] [and] mn [sx + 1 + 1 ]), min (minutes [ sx] [+ 1 ], mn [sx + 1 ], [and])); mx, sx] [and] = max (max (mx, sx] [and], mx, sx + 1 + 1 ]), max (mx, sx + 1 ], mx, sx + 1] [and])); } } } Int ans = 1 << 30 ; for ( int sx = a-n + 1 ; sx; sx-- ) for ( int a = b n + 1 ; and; sy-- ) ans = min (ans, mx, sx] [and] - Minutes [sx] [and]); printf ( " % d \ n " , ans); return 0 ; }
Then a quick read, 60-> 70
The last O2, too,
Then go in the other evaluation machine speed, do not open the whole O2 too ......
So minus-dimensional skills to learn
Well, next is a decent optimization,
(1) RMQ
The O (n) maintenance time becomes O (logn)
Note: log2 and log all keywords, variable names do not
#include<cstdio> #include<cstdlib> #include<algorithm> #include<cstring> using namespace std; int a,b,n; const int N=1003,M=103; int lg[N],d[8]; int mn[N][N][8],mx[N][N][8]; inline int read() { int x=0;char c=getchar(); while(c<'0' || c>'9') c=getchar(); while(c>='0'&&c<='9') x=(x<<3)+(x<<1)+c-'0',c=getchar(); return x; } int main() { a=read(),b=read(),n=read(); for(int i=2;i<=n;i++) lg[i]=lg[i>>1]+1; d[0]=1; for(int i=1;i<=lg[n];i++) d[i]=d[i-1]<<1; for(int i=1;i<=a;i++) for(int j=1;j<=b;j++) mx[i][j][0]=mn[i][j][0]=read(); int ans=1<<30,t1=lg[n],t2=d[t1]; for(int i=1;i<=t1;i++) { int r1=a-d[i]+1; for(int sx = 1 ; sx <= r1; sx ++ ) { int R2 = bd [i] + 1 ; for ( int = 1 ; and <= R2; and ++ ) { mn [sx] [and] [i] = min (min (mn [sx] [and] [i- 1 ], mn [sx + d [i - 1 ] + d [i- 1 ]] [i- 1 ]), min (mn [sx] [+ d [i- 1 ]] [i- 1 ], mn [sx + d [i - 1 ]] [and] [i- 1 ])); mx, sx] [and] [i] = max (max (mx, sx] [and] [i- 1 ], mx, sx + d [i- 1]] [+ d [i- 1 ]] [i- 1 ]), max (mx, sx + d [i- 1 ]] [i- 1 ], mx, sx + d [i- 1 ]] [and] [i- 1 ])); } } } For ( int sx = a, n + 1 , ex = a + 1 ; sx> 0 ; sx - ex-- ) for ( int a = b n + 1 , ey = b + 1 ; and> 0 ; and - ey-- ) { int A1 = max (max (mx, sx] [and] [t1], mx, sx] [ey-t2] [t1]), max (mx [ex-t2] and ] [t1], mx [ex-t2] [ey- t2] [t1])); an int A2 = Min (Min (MN [SX] [Sy] [t1 , ], MN [SX] [ - ey-t2 , ] [t1 , ]), Min (MN [Ex-t2 , ] [Sy] [t1 , ], MN [Ex -t2] [Ey- t2 , ] [t1 , ])); by ans = Min ( by ans, A1- A2); } The printf ( " d'% \ N " , by ans); Return 0 ; }
(2) AND
As two linear monotonic do dp
Copy From luogu:
My idea is ... monotonous queue maintenance rows and columns, respectively.
Specific method: the first is to maintain the value of each row in a monotonous queue, and A [] [] is the maximum value of each interval, the presence of X-minimum value [] [] and X [] [], respectively.
X-then [] [] and X [] [] are stored maximum and minimum values within the rectangle of 1 × n. X [i] [j] of the rectangular j ~ j + n-1 columns in the i-th row stored maximum value. Similarly, the first rectangular j ~ j + n-1 row x [i] [j] stored in the minimum value of the i-th row.
Then again these values on each column to maintain two arrays, the X-[] [] is the maximum value in each interval with the Y [] [] maintenance, the X [] [] in each section the minimum value Y [] [] maintenance. Then a rectangular maximum Y [i] [j] X-memory [] [] of the i ~ i + n-1 row and j column. Similarly y [i] [j] stored X [] [] in the minimum rectangle of i ~ i + n-1 row and j column.
Therefore, solid Y [i] [j] is stored in a [i ~ i + n-1] [j ~ j + n-1] is the largest, that is i, j is the upper left corner, the side length n the maximum value of the square. Similarly, y [i] [j] that is stored in the i, j is the upper left corner, the minimum side length of the square of n.
#include <cstdio> #include <the cstdlib> #include <Queue> #include <algorithm> the using namespace STD; int A, B, n-; const int N = 1003 , M = 103 ; int D [N] [N]; int MX [ 2 ] [N] [N], Mn [ 2 ] [N] [N]; // 0: (I, j) is represented by max (1, j-n + 1) to the j most values, the effective portion from the start n the deque < int > Ql, Q2; int main () { Scanf ( " % D% D% D " , & & B, A &, n); for(int i=1;i<=a;i++) { q1.clear() ,q2.clear() ; for(int j=1;j<=b;j++) { scanf("%d",&d[i][j]); if(!q1.empty() && q1.front() <= j-n) q1.pop_front() ; while(!q1.empty() && d[i][q1.back() ]<=d[i][j] ) q1.pop_back() ; q1.push_back(j); mx[0][i][j]=d[i][q1.front() ]; if(!q2.empty() && q2.front() <= j-n) q2.pop_front() ; while(!q2.empty() && d[i][q2.back() ]>=d[i][j] ) q2.pop_back() ; q2.push_back(j); mn[0][i][j]=d[i][q2.front() ]; } } for(int j=1;j<=b;j++) { q1.clear() ,q2.clear() ; for(int i=1;i<=a;i++) { if(!q1.empty() && q1.front() <= i-n) q1.pop_front() ; while(!q1.empty() && mx[0][q1.back() ][j]<=mx[0][i][j] ) q1.pop_back() ; q1.push_back(i); mx[1][i][j]=mx[0][q1.front() ][j]; if(!q2.empty() && q2.front() <= i-n) q2.pop_front() ; while(!q2.empty() && mn[0][q2.back() ][j]>=mn[0][i][j] ) q2.pop_back() ; q2.push_back(i); mn[1][i][j]=mn[0][q2.front() ][j]; } } int ans=mx[1][n][n]-mn[1][n][n]; for(int i=n;i<=a;i++) for(int j=n;j<=b;j++) Years = min (year, x [ 1 ] [i] [j] -mn [ 1 ] [i] [j]); printf ( " % d \ n " , year); return 0 ; }