樹鏈剖分 其實不難

2022-06-01 18:42:10 字數 2380 閱讀 3699

————來自chinhhh大佬的部落格 ——寫得真的很好(我也是看這篇看懂的)

#include using

namespace

std;

#define ls p << 1

#define rs p << 1 | 1

const

int maxn = 2 * 1e6 + 10

;int read() //

普通快讀

if (c == '-'

)

while (c >= '

0' && c <= '9'

)

return f *k;

}struct

node edge[maxn];

intfirst[maxn];

int num = 0;//

這裡存初始的樹,用的鄰接表

struct

tree t[maxn * 2

];//

這裡存線段樹:

//l,r:左右兒子。 sum:區間和。 siz:以當前節點為根的子樹大小(包括了自己)。 lazy:懶標記。

int n, m, root, mod, cnt = 0

, a[maxn], b[maxn];

void add(int x, int

y)int

deep[maxn], fa[maxn], son[maxn], tot[maxn], top[maxn], id[maxn];

int dfs1(int now, int f, int

dep)

return

tot[now];}//

找重兒子

void dfs2(int now, int

topf)

//處理重鏈

//-------------------以下為線段樹

void pushup(int

p)void build(int p, int ll, int

rr)

int mid = (ll + rr) >> 1

; build(ls, ll, mid);

build(rs, mid + 1

, rr);

pushup(p);

}void pushdown(int

p)void intervaladd(int p, int ll, int rr, int val) //

修改子樹

pushdown(p);

int mid = (t[p].l + t[p].r) >> 1

;

if (ll <=mid)

intervaladd(ls, ll, rr, val);

if (rr >mid)

intervaladd(rs, ll, rr, val);

pushup(p);

} //

由於我們處理過了,所以這裡的以p為根的子樹的編號是連續的,故可直接用線段樹的操作進行修改(相當於乙個小線段樹)

void treeadd(int x, int y, int

val)

if (deep[x] >deep[y])

swap(x, y);

intervaladd(

1, id[x], id[y], val);

} //

想著lca就懂了,只不過這裡用的是重鏈

int intervalquery(int p, int ll, int rr) //

求子樹的和 //

由於我們處理過了,所以這裡的以p為根的子樹的編號是連續的,故可直接用線段樹的操作進行修改(相當於乙個小線段樹)

int treequery(int x, int y) //

求最短路徑的和,依舊和lca差不多

if (deep[x] >deep[y])

swap(x, y);

ans = (ans + intervalquery(1, id[x], id[y])) %mod;

return

ans;

}int

main()

for (int i = 1; i <= n - 1; i++)

dfs1(root,

0, 1

); dfs2(root, root);

build(

1, 1

, n);

while (m--)

else

if (op == 2

) else

if (op == 3

) else

if (op == 4

) }

return0;

}

樹鏈剖分 樹鏈剖分講解

好了,這樣我們就成功解決了對樹上修改查詢邊權或點的問題。下面放上 vector v maxn int size maxn dep maxn val maxn id maxn hson maxn top maxn fa maxn 定義 int edge 1,num 1 struct tree e ma...

演算法入門 樹鏈剖分 輕重鏈剖分

目錄 3.0 求 lca 4.0 利用資料結構維護資訊 5.0 例題 參考資料 資料結構入門 線段樹 發表於 2019 11 28 20 39 dfkuaid 摘要 線段樹的基本 建樹 區間查詢 單點修改 及高階操作 區間修改 單點查詢 區間修改 區間查詢 標記下傳 標記永久化 閱讀全文 樹鏈剖分用...

樹鏈剖分 樹剖換根

這是一道模板題。給定一棵 n 個節點的樹,初始時該樹的根為 1 號節點,每個節點有乙個給定的權值。下面依次進行 m 個操作,操作分為如下五種型別 換根 將乙個指定的節點設定為樹的新根。修改路徑權值 給定兩個節點,將這兩個節點間路徑上的所有節點權值 含這兩個節點 增加乙個給定的值。修改子樹權值 給定乙...