樹鏈剖分求LCA的模板(洛谷P3379)

2021-10-05 19:27:17 字數 2093 閱讀 7830

2020.5.6

題目描述我就不寫了,模板題。

之前寫過倍增+tarjan求lca的板子,但是倍增這東西我貌似還沒太搞懂,只寫過st表,可能是我太菜了嗚嗚嗚。

樹剖其實我之前也沒太弄懂,後來做了一道河南某年的省選題就豁然開朗了(但還沒ac,可能是我用的線段樹板子出問題了)。就是用2遍dfs處理好樹內邊的歸屬關係 + 不斷向上溯祖,追溯到同乙個祖先即是答案。top陣列存放子樹頂節點編號,depth存放節點所處的層數,fa陣列是存節點的上乙個節點,son是重兒子,言外之意就是子樹中size最大的乙個子書根節點,然後size就是用來存子樹底下的節點數量。

這是lca,不過感覺樹剖和線段樹經常是配合使用的,因為一般都是要區間更新,所以乙個乙個查o(n)太慢了,需要先dfs序重新編號,然後建立線段樹,用乙個id陣列記錄編號,線段樹就能直接更新了,感覺還是很神奇的演算法。

**如下,前向星記得陣列開大,這題真**,我開了40w還是不夠,後來100w就ac了,毒瘤。

#include

using

namespace std;

#define limit (1000 + 5)

//防止溢位

#define inf 0x3f3f3f3f

#define inf 0x3f3f3f3f3f

#define lowbit(i) i&(-i)

//一步兩步

#define eps 1e-6

#define fastio ios::sync_with_stdio(false);cin.tie(0);

#define ff(a) printf("%lld\n",a );

#define pi(a,b) pair

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

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

#define mint(a,b,c) min(min(a,b), c)

#define mod 998244353

#define fopen freopen("c:\\users\\administrator01\\clionprojects\\untitled24\\data.txt", "rt", stdin)

typedef

long

long ll;

typedef

unsigned

long

long ull;

ll read()

while

(s >=

'0'&& s <=

'9')

return x * sign;

}//快讀

void

write

(ll x)

int n, k,cnt;

int head[limit]

,depth[limit]

,fa[limit]

,top[limit]

,sizes[limit]

,son[limit]

;struct nodeedge[limit<<2]

;void

init()

void

add(

int u,

int v)

void

dfs(

int u,

int pre)}}

void

dfs2

(int u,

int topp)

for(

int i = head[u]

;~i; i = edge[i]

.next)}}

intquery

(int x,

int y)

return depth[x]

< depth[y]

? x : y;

}int

main()

dfs(root,0)

;dfs2

(root, root)

;rep

(i ,

1, k)

return0;

}

樹鏈剖分 洛谷 P3384 模板 樹鏈剖分

step1 problem 題目 給你一棵n個點樹,m個操作,r是根,結果取模mod.操作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為根節點的子樹內所有節...

樹鏈剖分求LCA

這裡先推薦兩道練習的裸題 首先是求點 codevs4605 lca 就是求兩個點的公共祖先,每次詢問xor上上乙個詢問的答案。先是兩遍dfs dfs1 把dep siz son求出來 dfs2 求出top和w siz v 表示以v為根的子樹的節點數 dep v 表示v的深度 根深度為1 top v ...