#include using namespace std; using ull = unsigned long long; const int n = 400000,Log = 10; int check[n+1],Second[n]; pair table[19][n/Log]; pair Group[512][10][10]; pair Add[n/Log+1]; int belong[n/Log+1]; int check2[n+1],Second2[n]; pair table2[19][n/Log]; pair Group2[512][10][10]; pair Add2[n/Log+1]; int belong2[n/Log+1]; class SpecialSparseTable{ //LCA専用. private: int spos = 0,apos = 0,bpos = 0; pair op(pair &a,pair &b){return min(a,b);} pair add(pair &a,pair &b){return {a.first+b.first,a.second+b.second};} void maketable(const vector> &A){ int p2 = 1,l = 0,n = A.size(); for(int i=1; i<=n; i++){ if(i == p2) check[i] = l,p2 <<= 1,l++; else check[i] = check[i-1]; } for(int i=0; i>1)]); } } void makeGroup(const vector> &A){ int n = A.size(); const int loop = 1<<(Log-1); for(int i=0; i now(1); for(int k=0; k now.at(r)) mina = now.at(r),pos = r; Group[i][l][r] = {mina,pos}; } } } } pair tablerange(int l,int r){//[L,R)だよ. int len = r-l,pos = check[len]; return op(table[pos][l],table[pos][r-(1<> &A){ int n = A.size(); vector> sepa; for(int i=0; i now = {1001001001,-1}; for(int k=i; k A.at(k)) now = {A.at(k).first,k}; } Add[apos] = {A.at(i).first,i},apos++; belong[bpos] = g,bpos++; sepa.push_back(now); } maketable(sepa); makeGroup(A); } int rangeans(int l,int r){ //[l,r)! int l2 = (l+Log-1)/Log,r2 = r/Log; pair mind = {1001001001,-1}; if(l2 > r2) mind = add(Group[belong[r2]][l%Log][(r-1)%Log],Add[r2]); else{ if(l2 < r2) mind = tablerange(l2,r2); if(l%Log) mind = min(mind,add(Group[belong[l2-1]][l%Log][Log-1],Add[l2-1])); if(r%Log) mind = min(mind,add(Group[belong[r2]][0][(r-1)%Log],Add[r2])); } return Second[mind.second]; } }; int dist[200000],in[200000]; class LCA{ private: SpecialSparseTable ST; public: void make3(vector> &Graph,int root){ //直接グラフを渡す. int t = 0,dep = 0,n = Graph.size(),pos = root; vector> depth; vector Itr(n,-1),P(n,-1); while(pos != -1){ depth.push_back({dep,pos}); if(++Itr.at(pos) == 0) in[pos] = t; int to = P.at(pos); if(Itr.at(pos) == Graph.at(pos).size()) t++; else{ to = Graph.at(pos).at(Itr.at(pos)); if(to == P.at(pos)){ Itr.at(pos)++; if(Itr.at(pos) == Graph.at(pos).size()) t++; else to = Graph.at(pos).at(Itr.at(pos)); } } if(to != P.at(pos)) dist[to] = dist[pos]+1,P.at(to) = pos,t++,dep++; else dep--; pos = to; } ST.make(depth); } int twodist(int u,int v){ int tu = in[u],tv = in[v]; if(tu > tv) swap(tu,tv); int lca = ST.rangeans(tu,tv+1); return dist[u]+dist[v]-(dist[lca]<<1); } }; class SpecialSparseTable2{ //LCA専用. private: int spos = 0,apos = 0,bpos = 0; pair op(pair &a,pair &b){return min(a,b);} pair add(pair &a,pair &b){return {a.first+b.first,a.second+b.second};} void maketable(const vector> &A){ int p2 = 1,l = 0,n = A.size(); for(int i=1; i<=n; i++){ if(i == p2) check2[i] = l,p2 <<= 1,l++; else check2[i] = check2[i-1]; } for(int i=0; i>1)]); } } void makeGroup(const vector> &A){ const int loop = 1<<(Log-1),n = A.size(); for(int i=0; i now(1); for(int k=0; k now.at(r)) mina = now.at(r),pos = r; Group2[i][l][r] = {mina,pos}; } } } } pair tablerange(int l,int r){//[L,R)だよ. int len = r-l,pos = check2[len]; return op(table2[pos][l],table2[pos][r-(1<> &A){ int n = A.size(); vector> sepa; for(int i=0; i now = {1001001001,-1}; for(int k=i; k A.at(k)) now = {A.at(k).first,k}; } Add2[apos] = {A.at(i).first,i},apos++; belong2[bpos] = g,bpos++; sepa.push_back(now); } maketable(sepa); makeGroup(A); } int rangeans(int l,int r){ //[l,r)! int l2 = (l+Log-1)/Log,r2 = r/Log; pair mind = {1001001001,-1}; if(l2 > r2) mind = add(Group2[belong2[r2]][l%Log][(r-1)%Log],Add2[r2]); else{ if(l2 < r2) mind = tablerange(l2,r2); if(l%Log) mind = min(mind,add(Group2[belong2[l2-1]][l%Log][Log-1],Add2[l2-1])); if(r%Log) mind = min(mind,add(Group2[belong2[r2]][0][(r-1)%Log],Add2[r2])); } return Second2[mind.second]; } }; int dist2[200000],in2[200000]; class LCA2{ private: SpecialSparseTable2 ST; public: void make3(const vector> &Graph,int root){ //直接グラフを渡す. int t = 0,dep = 0,pos = root; const int n = 200000; vector> depth; vector Itr(n,-1),P(n,-1); while(pos != -1){ depth.emplace_back(pair{dep,pos}); if(++Itr.at(pos) == 0) in2[pos] = t; int to = P.at(pos); if(Itr.at(pos) == Graph.at(pos).size()) t++; else{ to = Graph.at(pos).at(Itr.at(pos)); if(to == P.at(pos)){ Itr.at(pos)++; if(Itr.at(pos) == Graph.at(pos).size()) t++; else to = Graph.at(pos).at(Itr.at(pos)); } } if(to != P.at(pos)) dist2[to] = dist2[pos]+1,P.at(to) = pos,t++,dep++; else dep--; pos = to; } ST.make(depth); } int twodist(int u,int v){ int tu = in2[u],tv = in2[v]; if(tu > tv) swap(tu,tv); int lca = ST.rangeans(tu,tv+1); return dist2[u]+dist2[v]-(dist2[lca]<<1); } }; int main(){ ios_base::sync_with_stdio(false); cin.tie(nullptr); int N; cin >> N; vector> Graph(200000),Graph2(200000); for(int i=0; i> u >> v; u--; v--; Graph.at(u).push_back(v); Graph.at(v).push_back(u); } for(int i=0; i> u >> v; u--; v--; Graph2.at(u).push_back(v); Graph2.at(v).push_back(u); } int n = 200000; for(int i=N; i