/* 前向星 */ structEdge { int nxt, to, w; }; vector<Edge> E; int head[N], Log2[N], fa[88][N], dep[N], w[N];
inlinevoidadd(int u, int v, int w){ E.push_back({ head[u], v, w }); head[u] = E.size() - 1; }
voidinitlca(int u, int fau = 0){ dep[u] = dep[fau] + 1; fa[0][u] = fau; for (int i = 1; i <= Log2[dep[u]]; ++i) { fa[i][u] = fa[i - 1][fa[i - 1][u]]; } // u的第2^{i-1}个父节点的第2^{i-1}个父节点即第2^{i}个父节点 for (int i = head[u]; i >= 1; i = E[i].nxt) { if (E[i].to != fau) { w[E[i].to] = E[i].w; // 将边权存储在子节点上 initlca(E[i].to, u); } } }
intgetlca(int u, int v){ if (dep[u] > dep[v]) std::swap(u, v); // -> dep[u]<=dep[v] while (dep[u] != dep[v]) v = fa[Log2[dep[v] - dep[u]]][v]; // -> dep[u]==dep[v] if (u == v) return u; for (int bit = Log2[dep[u]]; bit >= 0; --bit) { if (fa[bit][u] != fa[bit][v]) u = fa[bit][u], v = fa[bit][v]; } // 一步一步向上跳 return fa[0][u]; }
inlinevoidbeforeT(){ for (int i = 2; i < N; ++i) Log2[i] = Log2[i / 2] + 1; } // init Log2[]
/* 前向星和LCA略 */ int val[N]; inlinevoidinsert(int u, int v, int d = 1){ int Lca = getlca(u, v); val[u] += d; val[v] += d; val[Lca] -= d; val[fa[0][Lca]] -= d; }
voidgetsum(int u, int fau = 0){ for (int i = head[u]; i >= 1; i = E[i].nxt) { if (E[i].to != fau) { getsum(E[i].to, u); val[u] += val[E[i].to]; } } } // 差分的复原
voideachT(){ E.push_back({ -1,0,0 }); for { add(u, v, 0); add(v, u, 0); } // 前向星存边 initlca(rt); // LCA初始化 rt是树的根 for (int q = read(); q--; ) insert(u, v, d); // 做差分 getsum(st); // 差分的复原 for (int i = 1; i <= n; ++i) print(val[i]); }