Greetings everyone! We hope you enjoyed the problems. Here is the editorial of the contest
E — Travelling Salesman Problem
Try doing something with the lowest common ancestor of $$$i$$$ and $$$i + 1$$$.
Prefix sums on tree?
Since we have to answer the problem offline, let's try to do something similar to difference arrays.
First root the tree on an arbitrary vertex — say $$$1$$$.
Say the lowest common ancestor of $$$i$$$ and $$$i + 1$$$ be $$$LCA$$$. We will add $$$1$$$ to $$$score[parent_i]$$$ and $$$score[i + 1]$$$, and subtract $$$1$$$ from $$$score[LCA]$$$ and $$$score[parent_{LCA}]$$$. A Now if we add up scores going from bottom to top, we will get the number of times each vertex is visited.
Each vertex in the path from $$$parent_i$$$ to $$$LCA$$$ and $$$i + 1$$$ to $$$LCA$$$ will get $$$+1$$$ to the score. Note that the $$$LCA$$$ is considered twice, so we have subtracted $$$1$$$ from $$$score[LCA]$$$. Also to prevent any addition to parents of $$$LCA$$$, we have subtracted $$$score[parent_{LCA}]$$$ as well.
#include<bits/stdc++.h>
using namespace std;
#define int long long
// LCA code source - usaco.guide
int depth[200010];
int up[200010][20];
int score[200010];
vector<int> adj[200010];
void dfs(int v) {
for(int i = 1; i < 20; i++) { up[v][i] = up[up[v][i - 1]][i - 1]; }
for (int x : adj[v]) {
if (x != up[v][0]) {
depth[x] = depth[up[x][0] = v] + 1;
dfs(x);
}
}
}
int jump(int x, int d) {
for(int i = 0; i < 20; i++) {
if ((d >> i) & 1) x = up[x][i];
}
return x;
}
int LCA(int a, int b) {
if (depth[a] < depth[b]) swap(a, b);
a = jump(a, depth[a] - depth[b]);
if (a == b) return a;
for(int i = 19; i >= 0; i--) {
int aT = up[a][i], bT = up[b][i];
if (aT != bT) a = aT, b = bT;
}
return up[a][0];
}
void clear(int n) {
for(int i = 0; i < n; i++) {
score[i] = 0;
depth[i] = 0;
adj[i].clear();
for(int j = 0; j < 20; j++)
up[i][j] = 0;
}
}
int32_t main() {
ios_base::sync_with_stdio(false); cin.tie(0); cout.tie(0);
int t; cin >> t;
while(t--) {
int n; cin >> n;
clear(n + 5);
for(int i = 0; i < n - 1; i++) {
int a, b; cin >> a >> b;
adj[a].push_back(b);
adj[b].push_back(a);
}
dfs(1);
for(int i = 1; i < n; i++) {
int par = LCA(i, i + 1);
score[up[i][0]]++, score[i + 1]++;
score[par]--, score[up[par][0]]--;
}
vector<pair<int,int>> vp;
for(int i = 2; i <= n; i++) {
vp.push_back({-depth[i], i});
}
sort(vp.begin(), vp.end());
for(int i = 0; i < vp.size(); i++) {
score[up[vp[i].second][0]] += score[vp[i].second];
}
score[1]++; // initial stand
for(int i = 1; i <= n; i++) cout << score[i] << " ";
cout << "\n";
}
return 0;
}