洛谷 P3384 模板 樹鏈剖分

2021-09-27 16:29:56 字數 2235 閱讀 8966

樹鏈剖分大致是將樹劃分為若干條輕重邊和輕重鏈,其中關鍵的是重鏈和輕邊;

每次dfs先走重兒子(所在子樹點數多),對生成的dfs序建立線段樹維護;

該序列滿足重鏈在其中連續,子樹在其中連續;

對於鏈的操作,將兩端點不斷沿著重鏈向上走,最終走到同一條鏈,然後便可完成操作;

對於子樹的操作,記錄子樹大小,直接用線段樹維護即可。

#include

#include

using

namespace std;

inline

intread()

const

int maxn =

1e5+5;

int head[maxn]

, eid;

struct edge edge[

2* maxn]

;inline

void

insert

(int u,

int v)

int n, m, r, mod, a[maxn]

;int f[maxn]

, depth[maxn]

, size[maxn]

, best[maxn]

;int seq[maxn]

, order[maxn]

, cnt, first[maxn]

;void

dfs1

(int u,

int fa)

}void

dfs2

(int u,

int h)

}struct st t[

4* maxn]

;inline

voidup(

int p)

inline

void

mark

(int p,

int d)

inline

void

down

(int p)

}void

build

(int p,

int l,

int r)

int mid =

(l + r)

>>1;

build(2

* p, l, mid)

;build(2

* p +

1, mid +

1, r);up

(p);

}void

modify

(int p,

int x,

int y,

int d)

down

(p);

int mid =

(t[p]

.l + t[p]

.r)>>1;

if(x <= mid)

modify(2

* p, x, y, d);if

(y > mid)

modify(2

* p +

1, x, y, d);up

(p);

}int

query

(int p,

int x,

int y)

inline

void

modify0

(int p1,

int p2,

int d)

if(depth[p1]

> depth[p2]

)swap

(p1, p2)

;modify(1

, order[p1]

, order[p2]

, d);}

inline

intquery0

(int p1,

int p2)

if(depth[p1]

> depth[p2]

)swap

(p1, p2)

; ret =

(ret +

query(1

, order[p1]

, order[p2]))

% mod;

return ret;

}int

main()

dfs1

(r,0);

dfs2

(r, r)

;build(1

,1, n)

;while

(m--)}

return0;

}

洛谷 P3384 模板 樹鏈剖分

如題,已知一棵包含n個結點的樹 連通且無環 每個節點上包含乙個數值,需要支援以下操作 操作1 格式 1 x y z 表示將樹從x到y結點最短路徑上所有節點的值都加上z 操作2 格式 2 x y 表示求樹從x到y結點最短路徑上所有節點的值之和 操作3 格式 3 x z 表示將以x為根節點的子樹內所有節...

P3384 模板 樹鏈剖分 洛谷

題目鏈結 如題,已知一棵包含n個結點的樹 連通且無環 每個節點上包含乙個數值,需要支援以下操作 操作1 格式 1 x y z 表示將樹從x到y結點最短路徑上所有節點的值都加上z 操作2 格式 2 x y 表示求樹從x到y結點最短路徑上所有節點的值之和 操作3 格式 3 x z 表示將以x為根節點的子...

洛谷 P3384 模板 樹鏈剖分

樹鏈剖分詳情 跳轉大佬部落格 解題心得 個人看來其實樹鏈剖分就是把一棵標號沒有實際意義的樹重新標號,標號的規則按照重鏈優先,在有序之後用線段樹之類的資料結構來維護。include using namespace std const int maxn 1e5 100 struct node node ...