樹鏈剖分求lca

2022-09-20 08:03:13 字數 1229 閱讀 6606

題目描述

給一棵有根樹,以及一些詢問,每次詢問樹上的2 個節點a、b,求它們的最近公共祖先.

輸入第一行乙個整數n.接下來n 個數,第i 個數fi 表示i 的父親是fi. 若fi = 0,則i 為樹根.

接下來乙個整數m.接下來m 行,每行2 個整數a、b,詢問節點(a xor lastans)、(bxor lastans)的最近公共祖先. 其中lastans 為上乙個詢問的答案,一開始lastans = 0.

輸出對每乙個詢問輸出相應的答案.

樣例輸入

100 1 2 3 2 4 2 5 4 9

103 9

2 77 8

1 10 6

6 11

6 310 7

2 15

7 7樣例輸出31

4524

2525

#define _crt_secure_no_warnings

#include#include#include#include#include#includeusing namespace std;

const int maxn = 5e5 + 5;

vectormap[maxn];

int vis[maxn];

int fa[maxn];

int size[maxn];

int mainson[maxn];

int depth[maxn];

int root;

void dfs1(int v) }}

int path[maxn];

void dfs2(int u) }}

int lca(int a, int b)

return depth[a] < depth[b] ? a : b;

}int main()

} memset(vis, 0, sizeof(vis)); depth[root] = 0;

dfs1(root);

memset(vis, 0, sizeof(vis)); path[root] = root;

dfs2(root);

int m;scanf("%d", &m);

int lastans = 0;

//for (int i = 1; i <= n; i++)printf("%d\n", depth[i]);

for (int i = 1; i <= m; i++)

}

樹鏈剖分求LCA

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

樹鏈剖分(1) 樹剖求LCA

先看乙個樹剖的經典應用 初始化 先dfs一遍子樹,統計出每乙個點x的重兒子son x 和以x為根節點的子樹的大小siz x 這裡選擇x中子樹大小最大的兒子作為它的重兒子,第二遍dfs劃分樹鏈 重兒子與其父親節點劃分到一條鏈。其他的兒子為x的輕兒子,但屬於新的鏈的頂端元素。void dfs1 int ...

樹鏈剖分 入門(求LCA)

顧名思義,樹鏈剖分就是將樹剖分成一條一條的鏈,之後快速的操作鏈。樹鏈剖分的複雜度為,預處理兩遍dfs,o n 複雜度 之後查詢或者修改操作每一條鏈為o log n 因為剖分出來的鏈一共有log n 條,當然如果在鏈上再套個線段樹,那每次操作就是o log2 n 之後,下文只利用樹鏈剖分求樹上兩點的最...