meaning of the title
Sol
Long chain partition
It's also a kind of violence optimized by various fancy techniques
Its main idea is: for each node, the deepest child node is regarded as the heavy son, and the edge between them is regarded as the heavy edge
It's going to have some very good light weight
The sum of all chain lengths is $O(n) $level
The subtree depth of the $k $level ancestor of any point $\ geqslant k$
First of all, we maintain what are $len[i] $nodes up each heavy chain head, and what are $len[i] $nodes down the heavy chain
$len[i] $indicates the length of the heavy chain of the node
At the same time, preprocess the multiplication array to find the ancestor
For each query, first find the first binary bit of $k $(assumed to be $r $), use the multiplication array to jump up $2^r $, and then combine the array corresponding to the processed heavy chain head to judge
Time complexity:
Preprocess multiply array complexity to $O(nlogn)$
The first bit complexity of preprocessing each number is $O(n)$
$O(1) per query$
Total complexity is $O(nlogn + m)$
#include<bits/stdc++.h> using namespace std; const int MAXN = 3e5 + 10; inline int read() { char c = getchar(); int x = 0, f = 1; while(c < '0' || c > '9') {if(c == '-') f = -1; c = getchar();} while(c >= '0' && c <= '9') x = x * 10 + c - '0', c = getchar(); return x * f; } int N, md[MAXN], dep[MAXN], fa[MAXN][21], son[MAXN], top[MAXN], len[MAXN], B[MAXN]; vector<int> v[MAXN], U[MAXN], D[MAXN];//up and down void dfs(int x, int _fa) { md[x] = dep[x] = dep[_fa] + 1; fa[x][0] = _fa; for(int i = 1; i < 20; i++) if(fa[x][i - 1]) fa[x][i] = fa[fa[x][i - 1]][i - 1]; else break; for(int i = 0, to; i < v[x].size(); i++) { if((to = v[x][i]) == _fa) continue; dfs(to, x); if(md[to] > md[son[x]]) son[x] = to, md[x] = md[to]; } } void dfs2(int x, int topf) { top[x] = topf; len[x] = md[x] - dep[topf] + 1; if(!son[x]) return ; dfs2(son[x], topf); for(int i = 0, to; i < v[x].size(); i++) if(!top[(to = v[x][i])]) dfs2(to, to); } void Pre() { int now = 0; for(int i = 1; i <= N; i++) { if(!(i & (1 << now))) now++; B[i] = now; } for(int i = 1; i <= N; i++) { if(i == top[i]) { for(int j = 1, x = i; j <= len[i] && x; j++) x = fa[x][0], U[i].push_back(x); for(int j = 1, x = i; j <= len[i] && x; j++) x = son[x], D[i].push_back(x); } } } int Query(int x, int k) { if(k > dep[x]) return 0; if(k == 0) return x; x = fa[x][B[k]]; k ^= 1 << B[k]; if(!k) return x; if(dep[x] - dep[top[x]] == k) return top[x]; if(dep[x] - dep[top[x]] < k) return U[top[x]][k - dep[x] + dep[top[x]] - 1]; else return D[top[x]][dep[x] - dep[top[x]] - k - 1]; } int main() { N = read(); for(int i = 1; i <= N - 1; i++) { int x = read(), y = read(); v[x].push_back(y); v[y].push_back(x); } dfs(1, 0); dfs2(1, 1); Pre(); int lastans = 0, Q = read(); while(Q--) { int x = read() ^ lastans, y = read() ^ lastans; printf("%d\n", lastans = Query(x, y)); } return 0; }