有一面長 10,000,000 字節的牆壁,依次貼上 n(≤10,000)張海報,每張海報覆蓋連續區間 [li, ri]。後貼的海報會覆蓋前者。求最終可見的海報數量(至少有一字節可見即算可見)。
cover 標記:1 表示該區間已被完全覆蓋。pushdown 時將標記下傳給子節點。query(pos, L, R) 返回 1 表示該區間有未覆蓋部分(即海報可見),並將該區間標記為覆蓋;返回 0 表示已完全覆蓋。文中給出兩份代碼,第一份在 query 入口直接判斷 f[pos].cover,第二份移除該判斷改用 pushdown。第一份邏輯更直觀且正確;第二份若缺少入口判斷會導致重複計數。建議採用第一種寫法。
int query(int pos, int L, int R) {
if (f[pos].cover) return 0; // 已全覆蓋
if (f[pos].le == L && f[pos].ri == R) { // 精確匹配區間
f[pos].cover = 1;
return 1; // 可見
}
int mid = (f[pos].le + f[pos].ri) >> 1;
int res = 0;
if (mid >= R) res = query(L(pos), L, R);
else if (mid < L) res = query(R(pos), L, R);
else res = query(L(pos), L, mid) | query(R(pos), mid+1, R);
if (f[L(pos)].cover && f[R(pos)].cover) f[pos].cover = 1;
return res;
}