#include #include #include #include #include constexpr int ntiers = 17; int lca(int a, int b, const std::vector &firstidx, const std::vector &lastidx, const std::vector &lift) { int n = firstidx.size(); int tier = ntiers-1; while(lastidx[b] < firstidx[a] || lastidx[b] > lastidx[a]) { while(tier > 0 && firstidx[lift[tier*n + a]] <= lastidx[b] && lastidx[b] <= lastidx[lift[tier*n + a]]) tier--; a = lift[tier*n+a]; } return a; } int main() { int n; std::cin >> n; std::vector nodecolor(n); for(int i=0; i> c; nodecolor[i] = c-1; } std::vector > edges(n-1); std::vector > adj(n); for(int i=0; i> v1 >> v2; edges[i] = {v1-1, v2-1}; adj[v1-1].push_back(v2-1); adj[v2-1].push_back(v1-1); } // build tree std::vector > children(n); std::vector parent(n); std::vector visited(n); std::stack tovisit; tovisit.push(0); parent[0] = 0; while(!tovisit.empty()) { int next = tovisit.top(); tovisit.pop(); visited[next] = true; for(auto it : adj[next]) { if(visited[it]) continue; children[next].push_back(it); parent[it] = next; tovisit.push(it); } } // LCA std::vector firstidx(n); std::vector lastidx(n); struct Visit { int node; bool first; }; std::stack vs; vs.push({0, true}); int idx=0; while(!vs.empty()) { Visit v = vs.top(); vs.pop(); if(v.first) { firstidx[v.node] = idx; vs.push({v.node, false}); for(auto c : children[v.node]) vs.push({c, true}); } else { lastidx[v.node] = idx; } idx++; } std::vector lift(n*ntiers); for(int i=0; i > nodecolors(n); // fact: all nodes in the color-c subtree are LCAs of consecutive color c nodes struct ColoredNode { int node; int idx; bool operator<(const ColoredNode &other) const { return idx < other.idx; } }; std::vector > colornodes(n); for(int i=0; i colorparent(n); for(int i=0; i nodescore(n); std::vector nodescoredelta(n); std::stack > undo; vs.push({0, true}); while(!vs.empty()) { Visit v = vs.top(); vs.pop(); if(v.first) { for(auto it : nodecolors[v.node]) { undo.push({it.first, colorparent[it.first]}); colorparent[it.first] = v.node; } vs.push({v.node, false}); for(auto it : children[v.node]) vs.push({it, true}); } else { int64_t score = 0; for(auto it : children[v.node]) score += nodescore[it]; score += nodescoredelta[v.node]; for(auto it : nodecolors[v.node]) { colorparent[undo.top().first] = undo.top().second; undo.pop(); } for(auto it : nodecolors[v.node]) { int64_t nc = colornodes[it.first].size(); int64_t c = it.second; int64_t delta = c * (nc - c); score += delta; int cparent = colorparent[it.first]; if(cparent != -1) { nodescoredelta[cparent] -= delta; nodecolors[cparent][it.first] += it.second; } } nodescore[v.node] = score; } } // finally, answer queries for(auto it : edges) { if(parent[it.first] == it.second) { std::cout << nodescore[it.first] << std::endl; } else { std::cout << nodescore[it.second] << std::endl; } } }