有乙個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個非負整數,表示矩陣中相應位置上的數。每行相鄰兩數之間用一空格分隔。輸出格式 僅乙個整數...