題目意思比較簡單, 就不在這裡贅述了
本著練習平衡樹的思路, 我把方法嘗試往上面去套, 結果想不出
只能棄掉平衡樹
最後想出來的方法是這樣的
我們運用類似於高維字首和那樣一維一維加上去的方法
先橫著統計在某個範圍內和最小的 \(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的矩形。如果將花園中的每一塊土地的 肥沃度 定義為該塊土地上每乙個小塊肥沃度之和,那麼,...