洛谷P2216 理想的正方形 單調佇列

2021-09-16 20:29:36 字數 2360 閱讀 9590

有乙個n×m

n\times m

n×m的整數組成的矩陣,現請你從中找出乙個k×k

k\times k

k×k的正方形區域,使得該區域所有數中的最大值和最小值的差最小。

樸素的想法是直接暴力列舉區間,然後列舉其中的每一位。時間複雜度o(n

m×k2

)o(nm\times k^2)

o(nm×k

2)。另一種思路是預處理所有邊長為k

kk的矩形中的最值。時間複雜度o(n

m×k)

o(nm\times k)

o(nm×k

)。然而這兩種方法都過不了。

n ,m

≤1000,k

≤100

n,m\leq 1000,k\leq 100

n,m≤10

00,k

≤100

,顯然是要一種o(n

m)

o(nm)

o(nm

)的方法。

考慮單調佇列。

先用單調佇列處理出hma

x[i]

[j

]hmax[i][j]

hmax[i

][j]

和h mi

n[i]

[j

]hmin[i][j]

hmin[i

][j]

,表示第i

ii行第j∼j

+k−1

j\sim j+k-1

j∼j+k−

1個數的最值。顯然是可以o(n

m)

o(nm)

o(nm

)搞的。

然後再用一次單調佇列處理出lma

x[i]

[j

]lmax[i][j]

lmax[i

][j]

和l mi

n[i]

[j

]lmin[i][j]

lmin[i

][j]

但是這裡表示的是第i

ii列max

/min

max/min\

max/mi

n。最後列舉區間,直接用lma

x[i]

[j]−

lmin

[i][

j]

lmax[i][j]-lmin[i][j]

lmax[i

][j]

−lmi

n[i]

[j]來更新答案就好了。

似乎還可以用stst

st表去做,時間複雜度o(n

m×lo

gk

)o(nm\times log\ k)

o(nm×l

ogk)

#include

#include

#include

#include

using

namespace std;

const

int n=

1010

;int n,m,k,a[n]

[n],hmax[n]

[n],hmin[n]

[n],lmax[n]

[n],lmin[n]

[n],ans;

deque<

int> qmax,qmin;

intmain()

while

(qmax.

size()

) qmax.

pop_back()

;while

(qmin.

size()

) qmin.

pop_back()

;}for(

int j=

1;j<=m-k+

1;j++

)while

(qmax.

size()

) qmax.

pop_back()

;while

(qmin.

size()

) qmin.

pop_back()

;}ans=

2147483647

;for

(int i=

1;i<=n-k+

1;i++

)for

(int j=

1;j<=m-k+

1;j++

) ans=

min(ans,lmax[i]

[j]-lmin[i]

[j])

;printf

("%d"

,ans)

;return0;

}

洛谷P2216 理想的正方形

題目 有可以直接找 maxn i j t 為 i,j 為左下角長度為t的正方形內的最大值。然後可以有以下轉移 maxn i j t max maxn i 1 j t 1 maxn i j t 1 maxn i j 1 t 1 maxn i 1 j 1 t 1 然後考慮滾動陣列,最後答案直接列舉即可。...

洛谷P2216 理想的正方形 單調佇列

給出乙個n m n mn m的矩陣,現在要你從裡面找出乙個k k k kk k的矩陣,使得這個矩陣的最大值減去最小值最大。n,m 1e3 n,m leq1e3 n,m 1e 3。如果只是乙個序列,維護長度為k kk的區間的最大值減去最小值。直接用兩個單調佇列分別維護這個滑動視窗即可。那麼要維護乙個矩...

P2216 HAOI2007 理想的正方形()

題目鏈結 有乙個a乘b的整數組成的矩陣,現請你從中找出乙個nn的正方形區域,使得該區域所有數中的最大值和最小值的差最小。輸入輸出格式 輸入格式 第一行為3個整數,分別表示a,b,n的值 第二行至第a 1行每行為b個非負整數,表示矩陣中相應位置上的數。每行相鄰兩數之間用一空格分隔。輸出格式 僅乙個整數...