#line 1 "..\\Main.cpp" #include #include #include #include using namespace std; #line 2 "D:\\Programming\\VSCode\\competitive-cpp\\nachia\\array\\csr-array.hpp" #include #line 5 "D:\\Programming\\VSCode\\competitive-cpp\\nachia\\array\\csr-array.hpp" namespace nachia{ template class CsrArray{ public: struct ListRange{ using iterator = typename std::vector::iterator; iterator begi, endi; iterator begin() const { return begi; } iterator end() const { return endi; } int size() const { return (int)std::distance(begi, endi); } Elem& operator[](int i) const { return begi[i]; } }; struct ConstListRange{ using iterator = typename std::vector::const_iterator; iterator begi, endi; iterator begin() const { return begi; } iterator end() const { return endi; } int size() const { return (int)std::distance(begi, endi); } const Elem& operator[](int i) const { return begi[i]; } }; private: int m_n; std::vector m_list; std::vector m_pos; public: CsrArray() : m_n(0), m_list(), m_pos() {} static CsrArray Construct(int n, std::vector> items){ CsrArray res; res.m_n = n; std::vector buf(n+1, 0); for(auto& [u,v] : items){ ++buf[u]; } for(int i=1; i<=n; i++) buf[i] += buf[i-1]; res.m_list.resize(buf[n]); for(int i=(int)items.size()-1; i>=0; i--){ res.m_list[--buf[items[i].first]] = std::move(items[i].second); } res.m_pos = std::move(buf); return res; } static CsrArray FromRaw(std::vector list, std::vector pos){ CsrArray res; res.m_n = pos.size() - 1; res.m_list = std::move(list); res.m_pos = std::move(pos); return res; } ListRange operator[](int u) { return ListRange{ m_list.begin() + m_pos[u], m_list.begin() + m_pos[u+1] }; } ConstListRange operator[](int u) const { return ConstListRange{ m_list.begin() + m_pos[u], m_list.begin() + m_pos[u+1] }; } int size() const { return m_n; } int fullSize() const { return (int)m_list.size(); } }; } // namespace nachia #line 6 "D:\\Programming\\VSCode\\competitive-cpp\\nachia\\tree\\centroid-decomposition-binary-tree copy.hpp" #include #include namespace nachia { struct CentroidDecompositionBinaryTree{ private: struct VectorIntView{ using Iter = typename std::vector::iterator; Iter li, ri; VectorIntView(std::vector& src, int l, int r) : li(src.begin() + l) , ri(src.begin() + r) {} Iter begin() const { return li; } Iter end() const { return ri; } int size() const { return ri - li; } int& operator[](int i) const { return li[i]; } }; struct CDBTNode{ int array_idx; int cd_depth; int sib; int parent; int array_left; int size; int exclude_cent; int component_root = 0; }; struct UpdatePoint { int i; int p; }; struct QueryRange { int i, l, r; }; std::vector> cd_dist; std::vector bt_nodes; std::vector> bt_arrays; std::vector> bt_arrays_sep; std::vector> update_points; QueryRange get_one_node_range(const CDBTNode& node, int l, int r){ QueryRange res; res.i = node.array_idx; res.l = bt_arrays_sep[res.i][node.array_left + std::max(0, std::min(l - node.exclude_cent, node.size))]; res.r = bt_arrays_sep[res.i][node.array_left + std::max(0, std::min(r - node.exclude_cent, node.size))]; return res; } VectorIntView array_for_node(std::vector>& src, const CDBTNode& node){ return VectorIntView(src[node.array_idx], node.array_left, node.array_left + node.size); } VectorIntView sep_for_node(std::vector>& src, const CDBTNode& node){ return VectorIntView(src[node.array_idx], node.array_left, node.array_left + (node.size + 1)); } static int find_centroid( const CsrArray& adj, std::vector& Z, int root ){ while(true){ int nx = -1; for(int c : adj[root]) if(Z[c] * 2 > Z[root]){ nx = c; break; } if(nx < 0) break; Z[root] -= Z[nx]; Z[nx] += Z[root]; root = nx; } return root; } public: CentroidDecompositionBinaryTree() {} CentroidDecompositionBinaryTree(const CsrArray& adj){ int n = adj.size(); assert(1 <= n); if(n == 1){ cd_dist = {{0}}; bt_nodes = {{0,0,-1,-1,0,1,0}}; bt_arrays = {{0}}; bt_arrays_sep = {{0,1}}; update_points = {{{0,0}}}; return; } std::vector Z; { std::vector bfs = {0}; std::vector P(n,-1); for(int i=0; i=1; i--) Z[P[bfs[i]]] += Z[bfs[i]]; } std::vector> cd_bfs; std::vector cd_bfs_adji = { 1 }; std::vector cd_dep(n, -1); std::vector cd_component_size(n); cd_bfs.push_back(std::make_pair(-1, find_centroid(adj, Z, 0))); cd_dep[cd_bfs.front().second] = 0; for(int i=0; i<(int)cd_bfs.size(); i++){ int g = cd_bfs[i].second; cd_component_size[g] = Z[g]; Z[g] = 0; for(int nx : adj[g]) if(cd_dep[nx] == -1){ int nxg = find_centroid(adj, Z, nx); cd_bfs.push_back(std::make_pair(nx, nxg)); cd_dep[nxg] = cd_dep[g] + 1; } cd_bfs_adji.push_back(cd_bfs.size()); } int cd_height = *std::max_element(cd_dep.begin(), cd_dep.end()); cd_dist.assign(cd_height+1, std::vector(n, -1)); for(int dep=0; dep<=cd_height; dep++){ std::vector bfs; for(int s=0; s dep) if(cd_dist[dep][e] == -1){ bfs.push_back(e); cd_dist[dep][e] = cd_dist[dep][p] + 1; } } } bt_nodes.resize(n*2-1); for(auto& v : bt_nodes) v.sib = v.array_idx = v.parent = -1; { std::vector cdbt_root_id(n); for(int i=0; i> bt_children(n*2-1); for(int i=0; i> Que; // ( -size, root ) for(int ii=n-1; ii>=0; ii--){ auto [nx,g] = cd_bfs[ii]; Que.push(std::make_pair(-1, g)); for(int ei=cd_bfs_adji[ii]; ei= 2){ auto a = Que.top().second; Que.pop(); auto b = Que.top().second; Que.pop(); int idx = cdbt_node_count; bt_nodes[a].sib = b; bt_nodes[b].sib = a; bt_nodes[a].parent = idx; bt_nodes[b].parent = idx; bt_nodes[idx].cd_depth = cd_dep[g]; bt_nodes[idx].size = bt_nodes[a].size + bt_nodes[b].size; bt_nodes[idx].exclude_cent = bt_nodes[a].exclude_cent & bt_nodes[b].exclude_cent; bt_nodes[a].component_root = g; bt_nodes[b].component_root = g; bt_children[idx] = std::make_pair(a,b); Que.push(std::make_pair(-bt_nodes[idx].size, idx)); cdbt_node_count++; } auto r = Que.top().second; Que.pop(); bt_nodes[r].cd_depth--; cdbt_root_id[g] = r; bt_nodes[r].exclude_cent = 1; } bt_nodes.back().array_idx = -1; std::vector arraysz(n*2-1); for(int idx=n*2-2; idx>=n; idx--){ auto [a,b] = bt_children[idx]; bt_nodes[a].array_idx = a; bt_nodes[a].array_left = arraysz[a]; arraysz[a] += bt_nodes[a].size; bt_nodes[b].array_idx = b; bt_nodes[b].array_left = arraysz[b]; arraysz[b] += bt_nodes[b].size; } bt_arrays.resize(arraysz.size()); for(int i=0; i<(int)arraysz.size(); i++) bt_arrays[i].resize(arraysz[i]); bt_arrays_sep.resize(arraysz.size()); for(int i=0; i<(int)arraysz.size(); i++) bt_arrays_sep[i].resize(arraysz[i] + 1); for(int idx=0; idx sep_buf(n+1, 0); for(int idx=n; idx<2*n-1; idx++) if(bt_nodes[idx].parent >= 0){ auto& node = bt_nodes[idx]; auto [a,b] = bt_children[idx]; int dep = node.cd_depth; auto array_view = array_for_node(bt_arrays, node); auto sep_view = sep_for_node(bt_arrays_sep, node); int ex = node.exclude_cent; for(int i=0; i<=node.size; i++) sep_buf[i] = 0; for(int p : array_for_node(bt_arrays, bt_nodes[a])) sep_buf[cd_dist[dep][p] - ex]++; for(int p : array_for_node(bt_arrays, bt_nodes[b])) sep_buf[cd_dist[dep][p] - ex]++; for(int i=0; i& get_array(int id) const { return bt_arrays[id]; } const std::vector& get_update_points(int vtx) const { return update_points[vtx]; } std::vector get_query_range(int from, int distl, int distr){ int p = from; std::vector res; if(distl <= 0 && 0 < distr){ res.push_back({ bt_nodes[p].array_idx, bt_nodes[p].array_left, bt_nodes[p].array_left + 1 }); } while(bt_nodes[p].parent != -1){ auto& sibnode = bt_nodes[bt_nodes[p].sib]; int d = cd_dist[sibnode.cd_depth][from]; auto tmp = get_one_node_range(sibnode, distl-d, distr-d); if(tmp.l < tmp.r) res.push_back(tmp); p = bt_nodes[p].parent; } return res; } }; } // namespace nachia #line 6 "D:\\Programming\\VSCode\\competitive-cpp\\nachia\\graph\\graph.hpp" namespace nachia{ struct Graph { public: struct Edge{ int from, to; void reverse(){ std::swap(from, to); } }; using Base = std::vector>; Graph(int n = 0, bool undirected = false, int m = 0) : m_n(n), m_e(m), m_isUndir(undirected) {} Graph(int n, const std::vector>& edges, bool undirected = false) : m_n(n), m_isUndir(undirected){ m_e.resize(edges.size()); for(std::size_t i=0; i static Graph Input(Cin& cin, int n, bool undirected, int m, bool offset = 0){ Graph res(n, undirected, m); for(int i=0; i> u >> v; res[i].from = u - offset; res[i].to = v - offset; } return res; } int numVertices() const noexcept { return m_n; } int numEdges() const noexcept { return int(m_e.size()); } int addNode() noexcept { return m_n++; } int addEdge(int from, int to){ m_e.push_back({ from, to }); return numEdges() - 1; } Edge& operator[](int ei) noexcept { return m_e[ei]; } const Edge& operator[](int ei) const noexcept { return m_e[ei]; } Edge& at(int ei) { return m_e.at(ei); } const Edge& at(int ei) const { return m_e.at(ei); } auto begin(){ return m_e.begin(); } auto end(){ return m_e.end(); } auto begin() const { return m_e.begin(); } auto end() const { return m_e.end(); } bool isUndirected() const noexcept { return m_isUndir; } void reverseEdges() noexcept { for(auto& e : m_e) e.reverse(); } void contract(int newV, const std::vector& mapping){ assert(numVertices() == int(mapping.size())); for(int i=0; i induce(int num, const std::vector& mapping) const { int n = numVertices(); assert(n == int(mapping.size())); for(int i=0; i indexV(n), newV(num); for(int i=0; i= 0) indexV[i] = newV[mapping[i]]++; std::vector res; res.reserve(num); for(int i=0; i= 0) res[mapping[e.to]].addEdge(indexV[e.from], indexV[e.to]); return res; } CsrArray getEdgeIndexArray(bool undirected) const { std::vector> src; src.reserve(numEdges() * (undirected ? 2 : 1)); for(int i=0; i::Construct(numVertices(), src); } CsrArray getEdgeIndexArray() const { return getEdgeIndexArray(isUndirected()); } CsrArray getAdjacencyArray(bool undirected) const { std::vector> src; src.reserve(numEdges() * (undirected ? 2 : 1)); for(auto e : m_e){ src.emplace_back(e.from, e.to); if(undirected) src.emplace_back(e.to, e.from); } return CsrArray::Construct(numVertices(), src); } CsrArray getAdjacencyArray() const { return getAdjacencyArray(isUndirected()); } private: int m_n; std::vector m_e; bool m_isUndir; }; } // namespace nachia #line 6 "D:\\Programming\\VSCode\\competitive-cpp\\nachia\\tree\\heavy-light-decomposition.hpp" namespace nachia{ struct HeavyLightDecomposition{ private: int N; std::vector P; std::vector PP; std::vector PD; std::vector D; std::vector I; std::vector rangeL; std::vector rangeR; public: HeavyLightDecomposition(const CsrArray& E = CsrArray::Construct(1, {}), int root = 0){ N = E.size(); P.assign(N, -1); I = {root}; I.reserve(N); for(int i=0; i<(int)I.size(); i++){ int p = I[i]; for(int e : E[p]) if(P[p] != e){ I.push_back(e); P[e] = p; } } std::vector Z(N, 1); std::vector nx(N, -1); PP.resize(N); for(int i=0; i=1; i--){ int p = I[i]; Z[P[p]] += Z[p]; if(nx[P[p]] == -1) nx[P[p]] = p; if(Z[nx[P[p]]] < Z[p]) nx[P[p]] = p; } for(int p : I) if(nx[p] != -1) PP[nx[p]] = p; PD.assign(N,N); PD[root] = 0; D.assign(N,0); for(int p : I) if(p != root){ PP[p] = PP[PP[p]]; PD[p] = std::min(PD[PP[p]], PD[P[p]]+1); D[p] = D[P[p]]+1; } rangeL.assign(N,0); rangeR.assign(N,0); for(int p : I){ rangeR[p] = rangeL[p] + Z[p]; int ir = rangeR[p]; for(int e : E[p]) if(P[p] != e) if(e != nx[p]){ rangeL[e] = (ir -= Z[e]); } if(nx[p] != -1){ rangeL[nx[p]] = rangeL[p] + 1; } } I.resize(N); for(int i=0; i PD[v]) u = P[PP[u]]; while(PP[u] != PP[v]){ u = P[PP[u]]; v = P[PP[v]]; } return (D[u] > D[v]) ? v : u; } int dist(int u, int v) const { return depth(u) + depth(v) - depth(lca(u,v)) * 2; } std::vector> path(int r, int c, bool include_root = true, bool reverse_path = false) const { if(PD[c] < PD[r]) return {}; std::vector> res(PD[c]-PD[r]+1); for(int i=0; i<(int)res.size()-1; i++){ res[i] = std::make_pair(rangeL[PP[c]], rangeL[c]+1); c = P[PP[c]]; } if(PP[r] != PP[c] || D[r] > D[c]) return {}; res.back() = std::make_pair(rangeL[r]+(include_root?0:1), rangeL[c]+1); if(res.back().first == res.back().second) res.pop_back(); if(!reverse_path) std::reverse(res.begin(),res.end()); else for(auto& a : res) a = std::make_pair(N - a.second, N - a.first); return res; } std::pair subtree(int p){ return std::make_pair(rangeL[p], rangeR[p]); } int median(int x, int y, int z) const { return lca(x,y) ^ lca(y,z) ^ lca(x,z); } int la(int from, int to, int d) const { if(d < 0) return -1; int g = lca(from,to); int dist0 = D[from] - D[g] * 2 + D[to]; if(dist0 < d) return -1; int p = from; if(D[from] - D[g] < d){ p = to; d = dist0 - d; } while(D[p] - D[PP[p]] < d){ d -= D[p] - D[PP[p]] + 1; p = P[PP[p]]; } return I[rangeL[p] - d]; } }; } // namespace nachia #line 9 "..\\Main.cpp" #include #include using i64 = long long; using u64 = unsigned long long; #define rep(i,n) for(int i=0; i<(int)(n); i++) const i64 INF = 1001001001001001001; i64 stadd(i64 a, i64 b){ return a+b; } i64 ste(){ return 0; } void testcase(){ int N; cin >> N; auto tree = nachia::Graph::Input(cin, N, true, N-1, 1); auto cd = nachia::CentroidDecompositionBinaryTree(tree.getAdjacencyArray()); auto hld = nachia::HeavyLightDecomposition(tree); using RQ = atcoder::fenwick_tree; auto C = vector(cd.get_array_count(), pair()); rep(i,C.size()){ C[i].first = RQ(cd.get_array(i).size() + 1); C[i].second = RQ(cd.get_array(i).size() + 1); } vector dist(N); rep(i,N-1) dist[i] = hld.dist(i,i+1); vector distsum(N); rep(i,N-1) distsum[i+1] = distsum[i] + dist[i]; dist[N-1] = 0; vector ans(N); // cout << "dist : "; rep(i,N){ cout << dist[i] << " "; } cout << endl; // cout << cd.get_array_count() << endl; for(int x=N-1; x>=0; x--){ // cout << "f "; // rep(k,N){ // i64 f = distsum[N-1]; // for(auto [i,p] : cd.get_update_points(k)){ // int g = cd.get_root_of(i); // int d = hld.dist(g, k); // f += C[i].first.sum(0, p+1); // f += C[i].second.sum(0, p+1) * d; // } // cout << f << " "; // } cout << endl; // cout << "x = " << x << endl; ans[x] += distsum[N-1]; for(auto [i,p] : cd.get_update_points(x)){ // cout << " i = " << i << " , p = " << p << endl; int g = cd.get_root_of(i); int d = hld.dist(g, x); ans[x] += C[i].first.sum(0, p+1); ans[x] += C[i].second.sum(0, p+1) * d; } if(x != N-1){ for(auto [i,l,r] : cd.get_query_range(x+1, 0, dist[x] - 1)){ int g = cd.get_root_of(i); int d = hld.dist(g, x+1) + 1; //cout << " i = " << i << " , g = " << g << " , d = " << d << " , l = " << l << " , r = " << r << endl; C[i].first.add(l, d - dist[x]); C[i].first.add(r, dist[x] - d); C[i].second.add(l, 1); C[i].second.add(r, -1); } } } rep(i,N) cout << ans[i] << '\n'; //cout << "##" << endl; } int main(){ ios::sync_with_stdio(false); cin.tie(nullptr); testcase(); return 0; }