In this HackerRank Fibonacci Numbers Tree problem we have given the configuration for the tree and a list of operations, perform all the operations efficiently.
Problem solution in Java Programming.
import java.io.ByteArrayInputStream; import java.io.IOException; import java.io.InputStream; import java.io.PrintWriter; import java.util.Arrays; import java.util.InputMismatchException; public class H { InputStream is; PrintWriter out; String INPUT = ""; void solve() { int n = ni(); int Q = ni(); par = new int[n]; for(int i = 1;i < n;i++){ par[i] = ni()-1; } par[0] = -1; int[][] g = parentToG(par); int[][] pars = parents3(g, 0); int[] ord = pars[1], dep = pars[2]; clus = decomposeToHeavyLight(g,par, ord); cluspath = clusPaths(clus, ord); clusiind = clusIInd(cluspath, n); int m = cluspath.length; sts = new SegmentTreeMatrix[m]; for(int i = 0;i < m;i++){ sts[i] = new SegmentTreeMatrix(cluspath[i].length); } int[][] spar = logstepParents(par); for(int z = 0;z < Q;z++){ char type = nc(); if(type == 'U'){ int x = ni()-1; long K = nl(); sts[clus[x]].update(clusiind[x], K); }else{ int mod = 1000000007; int x = ni()-1, y = ni()-1; int lca = lca2(x, y, spar, dep); long ret = d(x)+d(y)-d(lca)-d(par[lca]); ret %= mod; if(ret < 0)ret += mod; out.println(ret); } } } int[] par; int[] clus, clusiind; int[][] cluspath; SegmentTreeMatrix[] sts; long d(int x) { if(x == -1)return 0; int[] lcx = new int[100]; int[] lto = new int[100]; int p = 0; int cx = clus[x]; int ind = clusiind[x]; while (true) { lcx[p] = cx; lto[p] = ind+1; p++; int con = par[cluspath[cx][0]]; if(con == -1)break; ind = clusiind[con]; cx = clus[con]; } int[] v = {0, 0, 1, 0}; for(int i = p-1;i >= 0;i--){ v = sts[lcx[i]].apply(0, lto[i], v); } return v[3]; } public static class SegmentTreeMatrix { public int M, H, N; public int[][][] node; public static int mod = 1000000007; public static long BIG = 8L*mod*mod; public static int S = 4; public SegmentTreeMatrix(int n) { N = n; M = Integer.highestOneBit(Math.max(N-1, 1))<<2; H = M>>>1; node = new int[M][][]; for(int i = 0;i < N;i++){ node[H+i] = new int[S][S]; node[H+i][0][0] = 1; node[H+i][0][1] = 1; node[H+i][1][0] = 1; node[H+i][3][1] = 1; node[H+i][2][2] = 1; node[H+i][3][3] = 1; node[H+i][3][0] = 1; } for(int i = H-1;i >= 1;i--)propagate(i); } private void propagate(int cur) { node[cur] = prop2(node[2*cur], node[2*cur+1], node[cur]); } private int[][] prop2(int[][] L, int[][] R, int[][] C) { if(L != null && R != null){ C = mul(R, L, C, mod); return C; }else if(L != null){ return prop1(L, C); }else if(R != null){ return prop1(R, C); }else{ return null; } } private int[][] prop1(int[][] L, int[][] C) { if(C == null){ // C = L; // read only C = new int[S][]; for(int i = 0;i < S;i++){ C[i] = Arrays.copyOf(L[i], S); } }else{ for(int i = 0;i < S;i++){ C[i] = Arrays.copyOf(L[i], S); } } return C; } public void update(int pos, long x) { int[][] M = {{1, 1}, {1, 0}}; int[] v = {1, 0}; v = pow(M, v, x-1); node[H+pos][0][2] += v[0]; if(node[H+pos][0][2] >= mod)node[H+pos][0][2] -= mod; node[H+pos][1][2] += v[1]; if(node[H+pos][1][2] >= mod)node[H+pos][1][2] -= mod; node[H+pos][3][2] += v[0]; if(node[H+pos][3][2] >= mod)node[H+pos][3][2] -= mod; for(int i = H+pos>>>1;i >= 1;i>>>=1)propagate(i); } public int[] apply(int l, int r, int[] v){ return apply(l, r, 0, H, 1, v); } protected int[] apply(int l, int r, int cl, int cr, int cur, int[] v) { if(l <= cl && cr <= r){ return mul(node[cur], v, mod); }else{ int mid = cl+cr>>>1; if(cl < r && l < mid){ v = apply(l, r, cl, mid, 2*cur, v); } if(mid < r && l < cr){ v = apply(l, r, mid, cr, 2*cur+1, v); } return v; } } public static int[] mul(int[][] A, int[] v, int mod) { int m = A.length; int n = v.length; int[] w = new int[m]; for(int i = 0;i < m;i++){ long sum = 0; for(int k = 0;k < n;k++){ sum += (long)A[i][k] * v[k]; if(sum >= BIG)sum -= BIG; } w[i] = (int)(sum % mod); } return w; } public static int[][] mul(int[][] A, int[][] B, int[][] C, int mod) { int m = A.length; int n = A[0].length; int o = B[0].length; if(C == null)C = new int[m][o]; for(int i = 0;i < m;i++){ for(int j = 0;j < o;j++){ long sum = 0; for(int k = 0;k < n;k++){ sum += (long)A[i][k] * B[k][j]; if(sum >= BIG)sum -= BIG; } sum %= mod; C[i][j] = (int)sum; } } return C; } // A^e*v public static int[] pow(int[][] A, int[] v, long e) { for(int i = 0;i < v.length;i++){ if(v[i] >= mod)v[i] %= mod; } int[][] MUL = A; for(;e > 0;e>>>=1) { if((e&1)==1)v = mul(MUL, v); MUL = p2(MUL); } return v; } // int matrix*int vector public static int[] mul(int[][] A, int[] v) { int m = A.length; int n = v.length; int[] w = new int[m]; for(int i = 0;i < m;i++){ long sum = 0; for(int k = 0;k < n;k++){ sum += (long)A[i][k] * v[k]; if(sum >= BIG)sum -= BIG; } w[i] = (int)(sum % mod); } return w; } // int matrix^2 (be careful about negative value) public static int[][] p2(int[][] A) { int n = A.length; int[][] C = new int[n][n]; for(int i = 0;i < n;i++){ long[] sum = new long[n]; for(int k = 0;k < n;k++){ for(int j = 0;j < n;j++){ sum[j] += (long)A[i][k] * A[k][j]; if(sum[j] >= BIG)sum[j] -= BIG; } } for(int j = 0;j < n;j++){ C[i][j] = (int)(sum[j] % mod); } } return C; } } public static int lca2(int a, int b, int[][] spar, int[] depth) { if (depth[a] < depth[b]) { b = ancestor(b, depth[b] - depth[a], spar); } else if (depth[a] > depth[b]) { a = ancestor(a, depth[a] - depth[b], spar); } if (a == b) return a; int sa = a, sb = b; for (int low = 0, high = depth[a], t = Integer.highestOneBit(high), k = Integer .numberOfTrailingZeros(t); t > 0; t >>>= 1, k--) { if ((low ^ high) >= t) { if (spar[k][sa] != spar[k][sb]) { low |= t; sa = spar[k][sa]; sb = spar[k][sb]; } else { high = low | t - 1; } } } return spar[0][sa]; } protected static int ancestor(int a, int m, int[][] spar) { for (int i = 0; m > 0 && a != -1; m >>>= 1, i++) { if ((m & 1) == 1) a = spar[i][a]; } return a; } public static int[][] logstepParents(int[] par) { int n = par.length; int m = Integer.numberOfTrailingZeros(Integer.highestOneBit(n - 1)) + 1; int[][] pars = new int[m][n]; pars[0] = par; for (int j = 1; j < m; j++) { for (int i = 0; i < n; i++) { pars[j][i] = pars[j - 1][i] == -1 ? -1 : pars[j - 1][pars[j - 1][i]]; } } return pars; } public static int[] decomposeToHeavyLight(int[][] g, int[] par, int[] ord) { int n = g.length; int[] size = new int[n]; Arrays.fill(size, 1); for (int i = n - 1; i > 0; i--) size[par[ord[i]]] += size[ord[i]]; int[] clus = new int[n]; Arrays.fill(clus, -1); int p = 0; outer: for (int i = 0; i < n; i++) { int u = ord[i]; if (clus[u] == -1) clus[u] = p++; for (int v : g[u]) { if (par[u] != v && size[v] >= size[u] / 2) { clus[v] = clus[u]; continue outer; } } for (int v : g[u]) { if (par[u] != v) { clus[v] = clus[u]; break; } } } return clus; } public static int[][] clusPaths(int[] clus, int[] ord) { int n = clus.length; int[] rp = new int[n]; int sup = 0; for (int i = 0; i < n; i++) { rp[clus[i]]++; sup = Math.max(sup, clus[i]); } sup++; int[][] row = new int[sup][]; for (int i = 0; i < sup; i++) row[i] = new int[rp[i]]; for (int i = n - 1; i >= 0; i--) { row[clus[ord[i]]][--rp[clus[ord[i]]]] = ord[i]; } return row; } public static int[] clusIInd(int[][] clusPath, int n) { int[] iind = new int[n]; for (int[] path : clusPath) { for (int i = 0; i < path.length; i++) { iind[path[i]] = i; } } return iind; } public static int[][] parentToG(int[] par) { int n = par.length; int[] ct = new int[n]; for(int i = 0;i < n;i++){ if(par[i] >= 0){ ct[i]++; ct[par[i]]++; } } int[][] g = new int[n][]; for(int i = 0;i < n;i++){ g[i] = new int[ct[i]]; } for(int i = 0;i < n;i++){ if(par[i] >= 0){ g[par[i]][--ct[par[i]]] = i; g[i][--ct[i]] = par[i]; } } return g; } public static int[][] parents3(int[][] g, int root) { int n = g.length; int[] par = new int[n]; Arrays.fill(par, -1); int[] depth = new int[n]; depth[0] = 0; int[] q = new int[n]; q[0] = root; for (int p = 0, r = 1; p < r; p++) { int cur = q[p]; for (int nex : g[cur]) { if (par[cur] != nex) { q[r++] = nex; par[nex] = cur; depth[nex] = depth[cur] + 1; } } } return new int[][] { par, q, depth }; } static int[][] packU(int n, int[] from, int[] to) { int[][] g = new int[n][]; int[] p = new int[n]; for (int f : from) p[f]++; for (int t : to) p[t]++; for (int i = 0; i < n; i++) g[i] = new int[p[i]]; for (int i = 0; i < from.length; i++) { g[from[i]][--p[from[i]]] = to[i]; g[to[i]][--p[to[i]]] = from[i]; } return g; } void run() throws Exception { is = INPUT.isEmpty() ? System.in : new ByteArrayInputStream(INPUT.getBytes()); out = new PrintWriter(System.out); long s = System.currentTimeMillis(); solve(); out.flush(); if(!INPUT.isEmpty())tr(System.currentTimeMillis()-s+"ms"); } public static void main(String[] args) throws Exception { new H().run(); } private byte[] inbuf = new byte[1024]; private int lenbuf = 0, ptrbuf = 0; private int readByte() { if(lenbuf == -1)throw new InputMismatchException(); if(ptrbuf >= lenbuf){ ptrbuf = 0; try { lenbuf = is.read(inbuf); } catch (IOException e) { throw new InputMismatchException(); } if(lenbuf <= 0)return -1; } return inbuf[ptrbuf++]; } private boolean isSpaceChar(int c) { return !(c >= 33 && c <= 126); } private int skip() { int b; while((b = readByte()) != -1 && isSpaceChar(b)); return b; } private double nd() { return Double.parseDouble(ns()); } private char nc() { return (char)skip(); } private String ns() { int b = skip(); StringBuilder sb = new StringBuilder(); while(!(isSpaceChar(b))){ // when nextLine, (isSpaceChar(b) && b != ' ') sb.appendCodePoint(b); b = readByte(); } return sb.toString(); } private char[] ns(int n) { char[] buf = new char[n]; int b = skip(), p = 0; while(p < n && !(isSpaceChar(b))){ buf[p++] = (char)b; b = readByte(); } return n == p ? buf : Arrays.copyOf(buf, p); } private char[][] nm(int n, int m) { char[][] map = new char[n][]; for(int i = 0;i < n;i++)map[i] = ns(m); return map; } private int[] na(int n) { int[] a = new int[n]; for(int i = 0;i < n;i++)a[i] = ni(); return a; } private int ni() { int num = 0, b; boolean minus = false; while((b = readByte()) != -1 && !((b >= '0' && b <= '9') || b == '-')); if(b == '-'){ minus = true; b = readByte(); } while(true){ if(b >= '0' && b <= '9'){ num = num * 10 + (b - '0'); }else{ return minus ? -num : num; } b = readByte(); } } private long nl() { long num = 0; int b; boolean minus = false; while((b = readByte()) != -1 && !((b >= '0' && b <= '9') || b == '-')); if(b == '-'){ minus = true; b = readByte(); } while(true){ if(b >= '0' && b <= '9'){ num = num * 10 + (b - '0'); }else{ return minus ? -num : num; } b = readByte(); } } private static void tr(Object... o) { System.out.println(Arrays.deepToString(o)); } }
Problem solution in C++ programming.
#include <cstdio> #include <cassert> #include <cstdlib> #include <cstring> #include <ctime> #include <iostream> #include <algorithm> #include <vector> #include <map> #include <set> #include <climits> #include <cctype> #include <utility> #include <queue> #include <cmath> #include <complex> using namespace std; typedef long long LL; typedef pair<int, int> PII; typedef vector<int> VI; typedef vector<PII> VPII; typedef pair<LL, LL> PLL; typedef pair<int, LL> PIL; typedef pair<LL, int> PLI; typedef double DB; #define pb push_back #define mset(a, b) memset(a, b, sizeof a) #define all(x) (x).begin(), (x).end() #define bit(x) (1 << (x)) #define bitl(x) (1LL << (x)) #define sqr(x) ((x) * (x)) #define sz(x) ((int)(x.size())) #define cnti(x) (__builtin_popcount(x)) #define cntl(x) (__builtin_popcountll(x)) #define clzi(x) (__builtin_clz(x)) #define clzl(x) (__builtin_clzll(x)) #define ctzi(x) (__builtin_ctz(x)) #define ctzl(x) (__builtin_ctzll(x)) #define X first #define Y second #define Error(x) cout << #x << " = " << x << endl template <typename T, typename U> inline void chkmax(T& x, U y) { if (x < y) x = y; } template <typename T, typename U> inline void chkmin(T& x, U y) { if (y < x) x = y; } const int MOD = 1e9 + 7; const int MAXN = 111111; int n, m; VI adj[MAXN]; int f[17][MAXN]; int d[MAXN], st[MAXN], en[MAXN]; int b[3][MAXN]; int c[55][2][2]; int T; void dfs(int u) { st[u] = ++T; for (int i = 0; i < sz(adj[u]); i++) { d[adj[u][i]] = d[u] + 1; dfs(adj[u][i]); } en[u] = T; } void add(int p, int id, int x) { for (; p <= n; p += p & -p) { b[id][p] = (b[id][p] + x) % MOD; } } int get_sum(int p, int id) { int ret = 0; for (; p; p -= p & -p) { ret = (ret + b[id][p]) % MOD; } return ret; } PII get(LL e) { int a[2], _a[2]; a[0] = 1, a[1] = 0; for (int i = 50; i >= 0; i--) { if (e >> i & 1) { for (int j = 0; j < 2; j++) { LL s = 0; for (int k = 0; k < 2; k++) { s += (LL)a[k] * c[i][j][k]; } _a[j] = s % MOD; } memcpy(a, _a, sizeof a); } } return make_pair(a[0], a[1]); } inline int lca(int u, int v) { if (d[u] < d[v]) swap(u, v); for (int i = 16; i >= 0; i--) { if (d[f[i][u]] < d[v]) continue; u = f[i][u]; if (d[u] == d[v]) break; } if (u == v) return u; for (int i = 16; i >= 0; i--) { if (f[i][u] == f[i][v]) continue; u = f[i][u], v = f[i][v]; } return f[0][u]; } void change(int u, LL k) { k += 2*(MOD+1); PII x = get(k), y = get(k - d[u] + 1); add(st[u], 0, MOD-x.first); add(st[u], 1, y.first); add(st[u], 2, y.second); add(en[u]+1, 0, x.first); add(en[u]+1, 1, MOD-y.first); add(en[u]+1, 2, MOD-y.second); } int query(int u) { if (!u) { return 0; } PII x = get(d[u]); LL s0 = get_sum(st[u], 0), s1 = get_sum(st[u], 1), s2 = get_sum(st[u], 2); return (s0 + s1 * x.first + s2 * x.second) % MOD; } int main() { for (int i = 0; i < 2; i++) { for (int j = 0; j < 2; j++) { c[0][i][j] = !(i & j); } } for (int e = 1; e <= 50; e++) { for (int i = 0; i < 2; i++) { for (int j = 0; j < 2; j++) { LL s = 0; for (int k = 0; k < 2; k++) { s += (LL)c[e-1][i][k] * c[e-1][k][j]; } c[e][i][j] = s % MOD; } } } scanf("%d%d", &n, &m); for (int i = 2; i <= n; i++) { int x; scanf("%d", &x); adj[x].push_back(i), f[0][i] = x; } d[1] = 1; dfs(1); for (int i = 1; i <= 16; i++) { for (int j = 1; j <= n; j++) { f[i][j] = f[i-1][f[i-1][j]]; } } memset(b, 0, sizeof b); for (int i = 0; i < m; i++) { char t[5]; int u; scanf("%s%d", t, &u); if (t[0] == 'U') { LL k; scanf("%lld", &k); change(u, k); } else { int v; scanf("%d", &v); int w = lca(u, v), p = f[0][w], ans = 0; ans = (query(u)+query(v)) % MOD; ans = (ans+MOD-query(w)) % MOD; ans = (ans+MOD-query(p)) % MOD; printf("%dn", ans); } } return 0; }
Problem solution in C programming.
#include <stdio.h> #include <string.h> #include <stdlib.h> #define prime_base 1000000007 #define fib_cycle_mag 2000000016L static inline int mod_prime_base(int self) { return (self % prime_base) + (prime_base & (self >> 31)); } static inline int mod_long_prime(long self) { return (int)((self % (long)prime_base) + ((long)prime_base & (self >> 63))); } static inline unsigned mod_fib_cycle(long self) { return (unsigned)((self % fib_cycle_mag) + (fib_cycle_mag & (self >> 63))); } unsigned cached_fib[1 << 20] = {0}; #define array_cnt(self) (sizeof(self)/sizeof((self)[0])) void init_cached_fib() { unsigned at, prev = 1, next = 1; for (at = 1; at < array_cnt(cached_fib); at++) { cached_fib[at] = prev; prev = next; next += cached_fib[at]; next %= prime_base; } } unsigned fib(unsigned self) { if (self < array_cnt(cached_fib)) return cached_fib[self]; if (self & 1U) { self = (self + 1) >> 1; unsigned long self_fib = fib(self), other_fib = fib(self - 1); return (unsigned)((self_fib * self_fib + other_fib * other_fib) % prime_base); } unsigned long self_fib = fib(self >>= 1); return (unsigned)((self_fib * ((fib(self - 1) << 1) + self_fib)) % prime_base); } typedef int sum_t; static inline sum_t bit_sum(unsigned length, sum_t self[length], unsigned node) { sum_t total = 0; for (; node; node &= node - 1) total = mod_prime_base(total + self[node]); return total; } static inline void bit_update(unsigned length, sum_t self[length], unsigned node, sum_t delta) { for (; node < length; node += node & -node) self[node] = mod_prime_base(self[node] + delta); } static inline void bit_point_range_update(unsigned length, sum_t sums[length], unsigned low, unsigned high, sum_t delta) { bit_update(length, sums, low, delta); bit_update(length, sums, high + 1, mod_prime_base(-delta)); } static inline unsigned log2_floor(unsigned self) { static unsigned debruijn[] = { 0, 9, 1, 10, 13, 21, 2, 29, 11, 14, 16, 18, 22, 25, 3, 30, 8, 12, 20, 28, 15, 17, 24, 7, 19, 27, 23, 6, 26, 5, 4, 31 }; self |= self >> 1; self |= self >> 2; self |= self >> 4; self |= self >> 8; self |= self >> 16; return debruijn[(self * 0x07C4ACDDU) >> 27]; } unsigned nearest_common_ancestor( unsigned vertex_cnt, unsigned log2_dists, unsigned ancestors[log2_dists][vertex_cnt], unsigned *depths, unsigned source, unsigned target ) { if (depths[source] < depths[target]) { source ^= target; target ^= source; source ^= target; } for (; depths[target] < depths[source]; source = ancestors[log2_floor(depths[source] - depths[target])][source]); if (source == target) return source; unsigned low = 0; while ((depths[source] - low) > 1) { unsigned mid = log2_floor((depths[source] - low) >> 1); if (ancestors[mid][source] != ancestors[mid][target]) { source = ancestors[mid][source]; target = ancestors[mid][target]; } else low = depths[ancestors[mid][source]]; } return ancestors[0][source]; } static inline sum_t tree_path_sum(unsigned length, sum_t sums[3][length], unsigned *depths, unsigned *ids, unsigned at) { return mod_long_prime( (long)cached_fib[depths[at]] * bit_sum(length, sums[0], ids[at]) + (long)cached_fib[depths[at] + 1] * bit_sum(length, sums[1], ids[at]) - bit_sum(length, sums[2], ids[at]) ); } int main() { init_cached_fib(); unsigned at, vertex_cnt, queries; scanf("%u %u", &vertex_cnt, &queries); unsigned log2_dists = log2_floor(vertex_cnt) + 1, ancestors[log2_dists][vertex_cnt + 1], *descendants = memset( malloc(5 * (vertex_cnt + 1) * sizeof(unsigned)), 0, sizeof(unsigned) * ((vertex_cnt + 1) << 1) ), *indices = &descendants[vertex_cnt + 1], *weights = &indices[vertex_cnt + 1], *ids = &weights[vertex_cnt + 1], *depths = &ids[vertex_cnt + 1]; ancestors[0][1] = 0; indices[0] = 1; for (at = 2; at <= vertex_cnt; indices[ancestors[0][at++]]++) scanf("%u", &ancestors[0][at]); for (at = 0; at < log2_dists; ancestors[at++][0] = 0); for (at = 0; ++at <= vertex_cnt; indices[at] += indices[at - 1]); for (at = vertex_cnt + 1; --at; descendants[--indices[ancestors[0][at]]] = at); { unsigned history[vertex_cnt + 1]; memset(weights, 0, sizeof(weights[0]) * sizeof(unsigned)); depths[0] = 0; history[0] = 0; for (at = 1; at;) { unsigned root = history[at - 1], others = indices[root]; if (weights[root]) { for (; ancestors[0][descendants[others]] == root; weights[root] += weights[descendants[others++]]); at--; } else for (weights[root] = 1; ancestors[0][descendants[others]] == root; history[at++] = descendants[others++]) depths[descendants[others]] = depths[root] + 1; } ids[0] = 0; history[0] = 0; for (at = 1; at;) { unsigned weight = 1, root = history[--at], others = indices[root]; for (; ancestors[0][descendants[others]] == root; weight += weights[descendants[others++]]) { history[at++] = descendants[others]; ids[descendants[others]] = ids[root] + weight; } } } unsigned level; for (level = 1; level < log2_dists; level++) for (at = 0; ++at <= vertex_cnt; ancestors[level][at] = ancestors[level - 1][ancestors[level - 1][at]]); sum_t sums[3][++vertex_cnt]; memset(sums, 0, sizeof(sums)); long kth_fib; for (getchar(); queries--; getchar()) if (getchar() == 'U') { scanf("%u %ld", &at, &kth_fib); long kth_fibs[2] = { fib(mod_fib_cycle(kth_fib)), fib(mod_fib_cycle(kth_fib + 1)) }, *low_fibs = &(((long [3]){ [2] = fib(depths[at]), [1] = fib(depths[at] - 1), [0] = fib(((depths[at] > 1) ? (depths[at] - 2) : 1)) })[2]); #define odd_mask(self) (((int)((self) << 31) >> 30) | 1) bit_point_range_update( vertex_cnt, sums[0], ids[at], ids[at] + weights[at] - 1, mod_long_prime(odd_mask(depths[at]) * (kth_fibs[1] * low_fibs[-1UL] - kth_fibs[0] * low_fibs[0])) ); bit_point_range_update( vertex_cnt, sums[1], ids[at], ids[at] + weights[at] - 1, mod_long_prime(odd_mask(depths[at]) * (kth_fibs[0] * low_fibs[-1UL] - kth_fibs[1] * low_fibs[-2UL])) ); bit_point_range_update( vertex_cnt, sums[2], ids[at], ids[at] + weights[at] - 1, (unsigned)kth_fibs[1] ); } else { unsigned source, target, common; scanf("%u %u", &source, &target); common = nearest_common_ancestor(vertex_cnt, log2_dists, ancestors, depths, source, target); printf("%dn", mod_long_prime( (long)tree_path_sum(vertex_cnt, sums, depths, ids, source) + tree_path_sum(vertex_cnt, sums, depths, ids, target) - tree_path_sum(vertex_cnt, sums, depths, ids, common) - tree_path_sum(vertex_cnt, sums, depths, ids, ancestors[0][common]) ) ); } free(descendants); return 0; }