Title [brush] [dp] deque optimization ideal square

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 ; 
}
View Code

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 ; 
}
View Code

 

Guess you like

Origin www.cnblogs.com/xwww666666/p/11693051.html