BZOJ1047 理想的正方形

2021-08-22 07:15:21 字數 1416 閱讀 7552

time limit: 10 sec  memory limit: 162 mb

submit: 4137  solved: 2326

有乙個a*b的整數組成的矩陣,現請你從中找出乙個n*n的正方形區域,使得該區域所有數中的最大值和最小值

的差最小。

第一行為3個整數,分別表示a,b,n的值第二行至第a+1行每行為b個非負整數,表示矩陣中相應位置上的數。每

行相鄰兩數之間用一空格分隔。

100%的資料2<=a,b<=1000,n<=a,n<=b,n<=1000

僅乙個整數,為a*b矩陣中所有「n*n正方形區域中的最大整數和最小整數的差值」的最小值。

5 4 2

1 2 5 6

0 17 16 0

16 17 2 1

2 10 2 1

1 2 2 2

解析:先把每個位置往左 n 個單位中的最大最小值算出來(用單調佇列優化),然後對於同一列維護乙個單調佇列,這樣就能快速得到乙個矩陣的最大值、最小值了。

令f[ i ][ j ][ 0 ]表示(i , j)這個位置往左 n 個單位中最小值,f[ i ][ j ][ 1 ]為最大值,f[ i ][ j ][ 2 ]表示以(i , j)這個位置為結尾的矩形中的最小值,f[ i ][ j ][ 3 ]為最大值,詳細過程見**。

**:

#include using namespace std;

const int max=1010;

const int inf=1e9;

int n,m,k,ans=inf,head,tail;

int num[max][max],f[max][max][4],p[max<<3],q[max<<3];

inline int get_int()

for(;isdigit(c);c=getchar()) x=(x<<3)+(x<<1)+c-'0';

return x*f;

}inline int mn(int x,int y)

inline void pre()

head = tail = 0;

for(int j=1;j<=n;j++) p[j]=0;

for(int j=1;j<=m;j++)

}}inline void solve()

head = tail = 0;

for(int i=1;i<=n;i++) q[i]=0;

for(int i=1;i<=n;i++)

}}int main()

pre();

solve();

for(int i=k;i<=n;i++)

for(int j=k;j<=m;j++) ans=mn(ans,f[i][j][3]-f[i][j][2]);

cout

}

BZOJ 1047 理想的正方形

bzoj 1047 傳送門 1 先橫向用單調佇列求出每個數左邊 n 個數中的最值 2 再縱向利用橫向的結果用單調佇列進行相同的操作 通過以上操作將 a b 的矩陣轉化為了 a n 1 b n 1 的矩陣 相當於每個正方形被縮成了乙個點,而每個點的最值就代表著原正方形中的最值 tip 1 又被 1 2...

BZOJ 1047 理想的正方形

看到這到題,第一反應當然是暴搜一遍,但是資料較大,暴搜鐵定過不了,自然想到進行優化,優化的方案很多,每個人的思路可能不同,在這裡我的思路僅供參考。我的想法是用單調佇列 單調棧,當然簡單的單調佇列 單調棧只適用於一行資料,對於這道題要進行一定的組合和變換。根據題目的介紹,可以大致總結出以下資訊 第一,...

BZOJ 1047 理想的正方形 單調佇列

剛開始用二維rmq直接給超記憶體了。用單調佇列可以做到o n 2 的複雜度。具體是先把每行用單調佇列處理一下。再把處理後的用列單調佇列處理下。include include include include include include include include include include...