標記永久化

2022-05-12 10:36:26 字數 2494 閱讀 1822

標記永久化是線段樹的乙個技巧,常用於無法(或難以)進行\(pushdown\)的較複雜的資料結構如主席樹,樹套樹等。

如何做?對每個節點維護\(sum\)和\(add\)。

考慮修改,當詢問與當前區間重合時,更新\(add+=val\),對所有經過的區間\(sum+=val\cdot (r-l+1)\)。

void modify(int rt, int l, int r, int l, int r, int v)

if (r<=mid) modify(ls, l, mid, l, r, v);

else if (l>mid) modify(rs, mid+1, r, l, r, v);

else modify(ls, l, mid, l, mid, v),

modify(rs, mid+1, r, mid+1, r, v);

}

考慮詢問,累加經過的區間的\(add\),答案即為\(sum_+\sum add\cdot (r-l+1)\)。

int query(int rt, int l, int r, int l, int r, int add)

一道模板

普通線段樹區間加\(+\)區間求和,可以練練手。

#include#define int long long

#define rep(i, a, b) for (register int i=(a); i<=(b); ++i)

#define per(i, a, b) for (register int i=(a); i>=(b); --i)

using namespace std;

const int n=1000005;

int sum[n], add[n], a[n];

inline int read()

#define mid (l+r>>1)

#define ls (rt<<1)

#define rs (rt<<1|1)

void build(int rt, int l, int r)

build(ls, l, mid); build(rs, mid+1, r);

sum[rt]=sum[ls]+sum[rs];

}void modify(int rt, int l, int r, int l, int r, int v)

if (r<=mid) modify(ls, l, mid, l, r, v);

else if (l>mid) modify(rs, mid+1, r, l, r, v);

else modify(ls, l, mid, l, mid, v),

modify(rs, mid+1, r, mid+1, r, v);

}int query(int rt, int l, int r, int l, int r, int add)

#undef mid

#undef ls

#undef rs

signed main()

if (opt==2) printf("%lld\n", query(1, 1, n, x, y, 0));

}return 0;

}

一道應用

也算是主席樹上標記永久化的模板吧。

#includeusing namespace std;

typedef long long ll;

const int n=100005;

int rt[n], ls[n<<5], rs[n<<5], add[n<<5], tot, tim;

long long sum[n<<5];

inline int read()

int build(int rt, int l, int r)

int mid=(l+r)>>1;

ls[rt]=build(rt, l, mid); rs[rt]=build(rt, mid+1, r);

sum[rt]=sum[ls[rt]]+sum[rs[rt]];

return rt;

}int update(int oldrt, int l, int r, int l, int r, int x)

int mid=(l+r)>>1;

if (l<=mid) ls[rt]=update(ls[rt], l, r, l, mid, x);

if (r>mid) rs[rt]=update(rs[rt], l, r, mid+1, r, x);

return rt;

}long long query(int rt, int l, int r, int l, int r)

void clear()

int main()

if (opt=='q')

if (opt=='h')

if (opt=='b') tim=read();}}

return 0;

}

標記永久化

1 概述 在可持久化線段樹中,我們常常要使用區間修改操作。這時候,如果再用下傳標記再向上更新的方式 pushdown pushup 來實現就會變得十分麻煩 因為要可持久化嘛 那麼,有沒有一種實現線段樹區間修改的方式可以不用下傳標記或向上更新呢?有,那就是標記永久化。2 原理 標記永久化的原理簡單來說...

線段樹標記永久化

對於樹套樹,主席樹等使用到線段樹的比較複雜的資料結構,如果區間修改的話,打標記後pushdown或者pushup是很難做到的完全不行吧 所以這個時候,乙個神奇的東西誕生了。線段樹標記永久化,維護乙個標記,假設為cov,再維護乙個sum 假設修改區間 ql,qr 全部加上v 和平常一樣,到這個區間後c...

線段樹 標記永久化

一般線段樹做區間修改操作時,先是找到目標區間,然後修改該區間,並打下延遲標記,最後從目標區間自底向上,更新所有包含目標區間的區間的值 即pushup 當該區間子節點被訪問前,pushdown下推標記。這種維護區間的方式存在一點點弊端。例如用這種方式寫一棵可持久化線段樹,因為每次pushdown都相當...