題意分析
給出乙個 $m*n$ 的矩陣 $a$ ,要求從中選出乙個 $a*b$ 的矩陣 $b$ ,再從矩陣 $b$ 中選出乙個 $c*d$ 的矩陣 $c$ ,要求矩陣 $b,c$ 的邊界不能重合,求矩陣 $c$ 在矩陣 $b$ 中的補集的權值和的最大值。
思路分析
通過分析題目後可以發現本題可以用二維單調佇列進行求解,同時利用到了二維字首和。即先對其中一維進行求解,然後再求解另一維。
具體實現
1. 預處理二維字首和
設 $suml_$ 表示以 $(i,j)$ 為右下角的矩形 $b$ 的權值和, $sums_$ 表示以 $(i,j)$ 為右下角的矩形 $c$ 的權值和,$sum_$ 表示 $(i,j)$ 的二維字首和。遞推式顯然,就不贅述了。
2. 利用單調佇列求解列的答案
設 $f1_$ 表示以 $(i,j-b+d+1\sim j-1)$ 為右下角的矩陣 $c$ 中權值和的最大的矩陣,則對於每個 $j$ ,有:
3. 利用單調佇列求解列的答案
設 $f2_$ 表示以 $(i-a+c+1\sim i,j-b+d+1\sim j-1)$ 為右下角的矩陣 $c$ 中權值和的最大的矩陣,求解過程與上步類似,就不贅述了。
4. 遍歷一遍找出答案
此時 $suml_-f2_$ 就是以 $(i,j)$ 為右下角的矩陣 $b$ 的答案,遍歷所有矩陣 $b$ ,找出最大值即可。
有乙個需要注意的點,矩陣 $b,c$ 的邊界不能重合,在遞推的時候下標需要注意。舉例:$(c,d)$ 不能作為決策和答案,$(c+1,d+1)$ 只能作為決策而不能作為答案。
#include#include#includeusing namespace std;const int n=1100;
int m,n,a,b,c,d,ans;
int s[n][n],sum[n][n],suml[n][n],sums[n][n],f1[n][n],f2[n][n];
dequeq;
int main()
}//求解第一維
for(int j=b;j<=n;j++)
}//求解第二維
for(int i=a;i<=m;i++)
for(int j=b;j<=n;j++)
ans=max(ans,suml[i][j]-f2[i][j]); //找出答案
printf("%d",ans);
return 0;
}
HAOI2007 修築綠化帶
haoi2007 修築綠化帶 時間限制 1 s 記憶體限制 128 mb 問題描述 為了增添公園的景致,現在需要在公園中修築乙個花壇,同時在畫壇四周修建一片綠化帶,讓花壇被綠化帶圍起來。如果把公園看成乙個m n的矩形,那麼花壇可以看成乙個c d的矩形,綠化帶和花壇一起可以看成乙個a b的矩形。如果將...
HAOI2007 修築綠化帶
問題描述 為了增添公園的景致,現在需要在公園中修築乙個花壇,同時在畫壇四周修建一片綠化帶,讓花壇被綠化帶圍起來。如果把公園看成乙個m n的矩形,那麼花壇可以看成乙個c d的矩形,綠化帶和花壇一起可以看成乙個a b的矩形。如果將花園中的每一塊土地的 肥沃度 定義為該塊土地上每乙個小塊肥沃度之和,那麼,...
題解 HAOI2007 修築綠化帶
題目意思比較簡單,就不在這裡贅述了 本著練習平衡樹的思路,我把方法嘗試往上面去套,結果想不出 只能棄掉平衡樹 最後想出來的方法是這樣的 我們運用類似於高維字首和那樣一維一維加上去的方法 先橫著統計在某個範圍內和最小的 c d 矩陣,把貢獻算在範圍的右下角 注意,這裡保證了這個矩陣在以 i,j 為右下...