#include using namespace std; #define rep(i, a, b) for(int i = a; i < (b); ++i) #define trav(a, x) for(auto& a : x) #define all(x) x.begin(), x.end() #define sz(x) (int)(x).size() typedef long long ll; typedef pair pii; typedef vector vi; // Binary lifting from KACTL vector treeJump(vi& P){ int on = 1, d = 1; while(on < sz(P)) on *= 2, d++; vector jmp(d, P); rep(i,1,d) rep(j,0,sz(P)) jmp[i][j] = jmp[i-1][jmp[i-1][j]]; return jmp; } int jmp(vector& tbl, int nod, int steps){ rep(i,0,sz(tbl)) if(steps&(1< struct RMQ { vector> jmp; RMQ(const vector& V) : jmp(1, V) { for (int pw = 1, k = 1; pw * 2 <= sz(V); pw *= 2, ++k) { jmp.emplace_back(sz(V) - pw * 2 + 1); rep(j,0,sz(jmp[k])) jmp[k][j] = min(jmp[k - 1][j], jmp[k - 1][j + pw]); } } T query(int a, int b) { assert(a < b); // or return inf if a == b int dep = 31 - __builtin_clz(b - a); return min(jmp[dep][a], jmp[dep][b - (1 << dep)]); } }; // LCA from KACTL struct LCA { int T = 0; vi time, path, ret, depth, parent, ss; vector C_dir; // The tree but with directed edges rooted in 1 RMQ rmq; LCA(vector& C) : time(sz(C)), depth(sz(C), 0), parent(sz(C)), ss(sz(C),0), C_dir(sz(C), vi()), rmq((dfs(C,0,0), ret)) {} void dfs(vector& C, int v, int par) { time[v] = T++; ss[v]++; parent[v] = par; for (int y : C[v]) if (y != par) { path.push_back(v), ret.push_back(time[v]), depth[y] = depth[v]+1; dfs(C, y, v); C_dir[v].push_back(y); ss[v] += ss[y]; } } int lca(int a, int b) { if (a == b) return a; tie(a, b) = minmax(time[a], time[b]); return path[rmq.query(a, b)]; } int dist(int a, int b){return depth[a] + depth[b] - 2*depth[lca(a,b)];} // Not from KACTL: int step(int a, int b){ // Vertex one step from a in the direction of b if(a == b)return a; if(time[b] < time[a] || time[b] >= time[a] + ss[a])return parent[a]; int lo = 0; int hi = sz(C_dir[a]); while(lo < hi-1){ int mid = (lo+hi)/2; if(time[C_dir[a][mid]] <= time[b]){ lo = mid; } else{ hi = mid; } } int res = C_dir[a][lo]; assert(dist(b, res) + 1 == dist(a,b)); return res; } }; // Given a tree and a permutation, find which vertices have ants in them after the process. vector simulate_slow(vector &C, vector permutation){ int n = sz(permutation); vector active(n, 1); for(auto v : permutation){ // bfs from v queue Q; vector parent(n, -1); parent[v] = v; Q.push(v); while(!Q.empty()){ int a = Q.front(); Q.pop(); if(active[a]){ active[a] = 0; active[parent[a]] = 1; } for(auto b : C[a]){ if(parent[b] == -1){ parent[b] = a; Q.push(b); } } } } vector answer; for(int c1 = 0; c1 < n; c1++){ if(active[c1])answer.push_back(c1); } return answer; } // Same as simulate_slow, but O(nlogn) instead of O(n^2) vector simulate_fast(vector &C, vector permutation){ LCA lca(C); int n = sz(C); set leaves; vector active(n, 1); vector binlift = treeJump(lca.parent); vector deg; // # active neighbours for(int c1 = 0; c1 < sz(C); c1++){ deg.push_back(sz(C[c1])); if(sz(C[c1]) <= 1)leaves.insert(c1); } for(int v : permutation){ set new_leaves; if(!active[v]){ int leaf = *(leaves.begin()); int root = lca.lca(leaf, v); int lo = root; int hi; if(active[root]){ hi = v; } else{ hi = leaf; } for(int d = sz(binlift)-1; d >= 0; d--){ int distance = lca.dist(lo, hi); if(distance > (1 << d)){ int mid = binlift[d][hi]; if(active[mid] == active[lo]){ lo = mid; } else{ hi = mid; } } } int to = hi; int from = lo; if(active[to])swap(to, from); // spread to 'to' from 'from' active[to] = 1; deg[to] = 1; new_leaves.insert(to); deg[from]++; if(leaves.find(from) != leaves.end() && deg[from] > 1)leaves.erase(from); } for(int a : leaves){ if(a == v){ new_leaves.insert(a); continue; } int b = lca.step(a, v); active[a] = 0; deg[b]--; if(deg[b] <= 1){ new_leaves.insert(b); } } leaves = new_leaves; } vector ans; for(int c1 = 0; c1 < n; c1++){ if(active[c1])ans.push_back(c1); } return ans; }