Below is a code which uses binary rise approach with N*Log(N) complexity and N*Log(N) memory usage.
#define rep(i,lo,hi) for(int i=lo;i<=hi;++i) #define repr(i,hi,lo) for(int i=hi;i>=lo;--i) const int MAXN = 1 << 17; const int MAXB = 29; typedef int arr[MAXN]; vi G[MAXN]; arr H, Path; int B[MAXN][MAXB+1]; int N; // Preprocessing void BuildB(int u, int path[], int npath) { int pos = npath - 1; rep(i,0,MAXB) { if (pos >= 0) { B[u][i] = Path[pos]; pos -= (1 << i); } else { B[u][i] = 1; // Root } } } void Visit(int u, int h, int p) { BuildB(u, Path, h); H[u] = h; // height Path[h] = u; // add to path for (int i = 0; i < G[u].size(); ++i) { int v = G[u][i]; if (v == p) continue; Visit(v, h + 1, u); } } void PrepareTree() { Visit(1, 0, 0); } // LCA Queries int Upfrom(int u, int d) { repr(p,MAXB,0) { if (d >= (1 << p)) { d -= (1 << p); u = B[u][p]; } } return u; } int LCA(int u, int v) { if (H[u] < H[v]) swap(u, v); if (H[u] > H[v]) { int d = H[u] - H[v]; u = Upfrom(u, d); } if (u == v) return u; for (int p = MAXB; p >= 0; p--) { if (B[u][p] != B[v][p]) { // move up if can u = B[u][p]; v = B[v][p]; } } return B[u][0]; }
No comments:
Post a Comment