題解 HAOI2007 修築綠化帶

2022-05-07 22:39:18 字數 1238 閱讀 4816

題目意思比較簡單, 就不在這裡贅述了

本著練習平衡樹的思路, 我把方法嘗試往上面去套, 結果想不出

只能棄掉平衡樹

最後想出來的方法是這樣的

我們運用類似於高維字首和那樣一維一維加上去的方法

先橫著統計在某個範圍內和最小的 \(c * d\) 矩陣, 把貢獻算在範圍的右下角

注意, 這裡保證了這個矩陣在以 \((i, j)\) 為右下角的某個範圍之內

然後再豎著計算答案, 我們固定 \(a * b\) 矩形的右邊在某一列, 就只用考慮行的變化了

從上往下依次列舉右下角, 每次彈出不合法的, 然後跟合法的和的 \(max\) 做差取最大值

因為右下角儲存的是一段以它為右下端點, 長度為 \(b\) , 高度為 \(c\) , 的範圍內和最小的 \(c * d\) 矩陣

所以只要定了列, 它就不會超過列的影響範圍, 也就是說, 列上面不會有衝突

所以只用看行之間的影響即可

這兩步可以用單調佇列實現

#include #include #include #include const int n = 1005; 

using namespace std;

int n, m, a, b, c, d, w[n][n], sum[n][n], val[n][n], l, r, ans;

struct node q[n];

template < typename t >

inline t read()

while(c >= '0' && c <= '9') x = x * 10 + c - '0', c = getchar();

return x * w;

}int getsum(int x1, int y1, int x2, int y2)

int main()

memset(val, 0x3f, sizeof(val));

for(int tmp, i = c; i <= n; i++) }

for(int tmp, j = b - 1; j < m; j++)

while(l <= r && q[l].id <= i || q[l].id - a + 1 >= i - c + 1)

l++;

ans = max(ans, q[l].val - val[i][j]);

} }printf("%d\n", ans);

return 0;

}

HAOI2007 修築綠化帶 題解

題意分析 給出乙個 m n 的矩陣 a 要求從中選出乙個 a b 的矩陣 b 再從矩陣 b 中選出乙個 c d 的矩陣 c 要求矩陣 b,c 的邊界不能重合,求矩陣 c 在矩陣 b 中的補集的權值和的最大值。思路分析 通過分析題目後可以發現本題可以用二維單調佇列進行求解,同時利用到了二維字首和。即先...

HAOI2007 修築綠化帶

haoi2007 修築綠化帶 時間限制 1 s 記憶體限制 128 mb 問題描述 為了增添公園的景致,現在需要在公園中修築乙個花壇,同時在畫壇四周修建一片綠化帶,讓花壇被綠化帶圍起來。如果把公園看成乙個m n的矩形,那麼花壇可以看成乙個c d的矩形,綠化帶和花壇一起可以看成乙個a b的矩形。如果將...

HAOI2007 修築綠化帶

問題描述 為了增添公園的景致,現在需要在公園中修築乙個花壇,同時在畫壇四周修建一片綠化帶,讓花壇被綠化帶圍起來。如果把公園看成乙個m n的矩形,那麼花壇可以看成乙個c d的矩形,綠化帶和花壇一起可以看成乙個a b的矩形。如果將花園中的每一塊土地的 肥沃度 定義為該塊土地上每乙個小塊肥沃度之和,那麼,...