n 棟樓初始高度 0。每次修改某棟樓高度,查詢從原點 (0,0) 看去能看到多少棟樓(即斜率單調遞增的樓數)。n, m ≤ 10^5。
struct SegTree {
double mx[N<<2];
int cnt[N<<2];
// 計算右子樹在給定初始斜率 x 下的可見增量
int calc(int rt, int l, int r, double x) {
if (l == r) return mx[rt] > x;
int mid = (l+r)>>1;
if (mx[ls] <= x) return calc(rs, mid+1, r, x);
else return cnt[rt] - cnt[ls] + calc(ls, l, mid, x);
}
void pushup(int rt) {
mx[rt] = max(mx[ls], mx[rs]);
cnt[rt] = cnt[ls] + calc(rs, mid+1, r, mx[ls]);
}
void update(int rt, int l, int r, int pos, double val) {
if (l == r) { mx[rt] = val; cnt[rt] = 1; return; }
int mid = (l+r)>>1;
if (pos <= mid) update(ls, l, mid, pos, val);
else update(rs, mid+1, r, pos, val);
pushup(rt);
}
};
| 方法 | 修改 | 查詢 | 總體 |
|---|---|---|---|
| 分塊 | O(√(n log n)) | O(√(n/log n) * log n) | O(m √(n log n)) |
| 線段樹 | O(log² n) | O(1) (根節點 cnt) | O(m log² n) |
線段樹常數較大但理論更優,分塊代碼簡單實際常快。