#pragma once
#include<algorithm>
#include<utility>
#include<vector>usingnamespacestd;#include"heavy-light-decomposition.hpp"template<typenameG>structAuxiliaryTree{Gg;HeavyLightDecomposition<G>hld;AuxiliaryTree(constG&_g,introot=0):g(_g),hld(g,root){}// ps : 頂点集合// 返り値 : (aux tree, aux tree の頂点と g の頂点の対応表)// aux tree は 親->子 の向きの辺のみ含まれる// ps が空の場合は空のグラフを返すpair<vector<vector<int>>,vector<int>>get(vector<int>ps){if(ps.empty())return{};autocomp=[&](inti,intj){returnhld.down[i]<hld.down[j];};sort(begin(ps),end(ps),comp);for(inti=0,ie=ps.size();i+1<ie;i++){ps.push_back(hld.lca(ps[i],ps[i+1]));}sort(begin(ps),end(ps),comp);ps.erase(unique(begin(ps),end(ps)),end(ps));vector<vector<int>>aux(ps.size());vector<int>rs;rs.push_back(0);for(inti=1;i<(int)ps.size();i++){intl=hld.lca(ps[rs.back()],ps[i]);while(ps[rs.back()]!=l)rs.pop_back();aux[rs.back()].push_back(i);rs.push_back(i);}returnmake_pair(aux,ps);}};/**
* @brief Auxiliary Tree
*/
#line 2 "tree/auxiliary-tree.hpp"
#include<algorithm>
#include<utility>
#include<vector>usingnamespacestd;#line 2 "tree/heavy-light-decomposition.hpp"
#line 2 "graph/graph-template.hpp"
template<typenameT>structedge{intsrc,to;Tcost;edge(int_to,T_cost):src(-1),to(_to),cost(_cost){}edge(int_src,int_to,T_cost):src(_src),to(_to),cost(_cost){}edge&operator=(constint&x){to=x;return*this;}operatorint()const{returnto;}};template<typenameT>usingEdges=vector<edge<T>>;template<typenameT>usingWeightedGraph=vector<Edges<T>>;usingUnweightedGraph=vector<vector<int>>;// Input of (Unweighted) GraphUnweightedGraphgraph(intN,intM=-1,boolis_directed=false,boolis_1origin=true){UnweightedGraphg(N);if(M==-1)M=N-1;for(int_=0;_<M;_++){intx,y;cin>>x>>y;if(is_1origin)x--,y--;g[x].push_back(y);if(!is_directed)g[y].push_back(x);}returng;}// Input of Weighted Graphtemplate<typenameT>WeightedGraph<T>wgraph(intN,intM=-1,boolis_directed=false,boolis_1origin=true){WeightedGraph<T>g(N);if(M==-1)M=N-1;for(int_=0;_<M;_++){intx,y;cin>>x>>y;Tc;cin>>c;if(is_1origin)x--,y--;g[x].emplace_back(x,y,c);if(!is_directed)g[y].emplace_back(y,x,c);}returng;}// Input of Edgestemplate<typenameT>Edges<T>esgraph([[maybe_unused]]intN,intM,intis_weighted=true,boolis_1origin=true){Edges<T>es;for(int_=0;_<M;_++){intx,y;cin>>x>>y;Tc;if(is_weighted)cin>>c;elsec=1;if(is_1origin)x--,y--;es.emplace_back(x,y,c);}returnes;}// Input of Adjacency Matrixtemplate<typenameT>vector<vector<T>>adjgraph(intN,intM,TINF,intis_weighted=true,boolis_directed=false,boolis_1origin=true){vector<vector<T>>d(N,vector<T>(N,INF));for(int_=0;_<M;_++){intx,y;cin>>x>>y;Tc;if(is_weighted)cin>>c;elsec=1;if(is_1origin)x--,y--;d[x][y]=c;if(!is_directed)d[y][x]=c;}returnd;}/**
* @brief グラフテンプレート
*/#line 4 "tree/heavy-light-decomposition.hpp"
template<typenameG>structHeavyLightDecomposition{private:voiddfs_sz(intcur){size[cur]=1;for(auto&dst:g[cur]){if(dst==par[cur]){if(g[cur].size()>=2&&int(dst)==int(g[cur][0]))swap(g[cur][0],g[cur][1]);elsecontinue;}depth[dst]=depth[cur]+1;par[dst]=cur;dfs_sz(dst);size[cur]+=size[dst];if(size[dst]>size[g[cur][0]]){swap(dst,g[cur][0]);}}}voiddfs_hld(intcur){down[cur]=id++;for(autodst:g[cur]){if(dst==par[cur])continue;nxt[dst]=(int(dst)==int(g[cur][0])?nxt[cur]:int(dst));dfs_hld(dst);}up[cur]=id;}// [u, v)vector<pair<int,int>>ascend(intu,intv)const{vector<pair<int,int>>res;while(nxt[u]!=nxt[v]){res.emplace_back(down[u],down[nxt[u]]);u=par[nxt[u]];}if(u!=v)res.emplace_back(down[u],down[v]+1);returnres;}// (u, v]vector<pair<int,int>>descend(intu,intv)const{if(u==v)return{};if(nxt[u]==nxt[v])return{{down[u]+1,down[v]}};autores=descend(u,par[nxt[v]]);res.emplace_back(down[nxt[v]],down[v]);returnres;}public:G&g;introot,id;vector<int>size,depth,down,up,nxt,par;HeavyLightDecomposition(G&_g,int_root=0):g(_g),root(_root),id(0),size(g.size(),0),depth(g.size(),0),down(g.size(),-1),up(g.size(),-1),nxt(g.size(),root),par(g.size(),root){dfs_sz(root);dfs_hld(root);}pair<int,int>idx(inti)const{returnmake_pair(down[i],up[i]);}template<typenameF>voidpath_query(intu,intv,boolvertex,constF&f){intl=lca(u,v);for(auto&&[a,b]:ascend(u,l)){ints=a+1,t=b;s>t?f(t,s):f(s,t);}if(vertex)f(down[l],down[l]+1);for(auto&&[a,b]:descend(l,v)){ints=a,t=b+1;s>t?f(t,s):f(s,t);}}template<typenameF>voidpath_noncommutative_query(intu,intv,boolvertex,constF&f){intl=lca(u,v);for(auto&&[a,b]:ascend(u,l))f(a+1,b);if(vertex)f(down[l],down[l]+1);for(auto&&[a,b]:descend(l,v))f(a,b+1);}template<typenameF>voidsubtree_query(intu,boolvertex,constF&f){f(down[u]+int(!vertex),up[u]);}intlca(inta,intb){while(nxt[a]!=nxt[b]){if(down[a]<down[b])swap(a,b);a=par[nxt[a]];}returndepth[a]<depth[b]?a:b;}intdist(inta,intb){returndepth[a]+depth[b]-depth[lca(a,b)]*2;}};/**
* @brief Heavy Light Decomposition(重軽分解)
*/#line 9 "tree/auxiliary-tree.hpp"
template<typenameG>structAuxiliaryTree{Gg;HeavyLightDecomposition<G>hld;AuxiliaryTree(constG&_g,introot=0):g(_g),hld(g,root){}// ps : 頂点集合// 返り値 : (aux tree, aux tree の頂点と g の頂点の対応表)// aux tree は 親->子 の向きの辺のみ含まれる// ps が空の場合は空のグラフを返すpair<vector<vector<int>>,vector<int>>get(vector<int>ps){if(ps.empty())return{};autocomp=[&](inti,intj){returnhld.down[i]<hld.down[j];};sort(begin(ps),end(ps),comp);for(inti=0,ie=ps.size();i+1<ie;i++){ps.push_back(hld.lca(ps[i],ps[i+1]));}sort(begin(ps),end(ps),comp);ps.erase(unique(begin(ps),end(ps)),end(ps));vector<vector<int>>aux(ps.size());vector<int>rs;rs.push_back(0);for(inti=1;i<(int)ps.size();i++){intl=hld.lca(ps[rs.back()],ps[i]);while(ps[rs.back()]!=l)rs.pop_back();aux[rs.back()].push_back(i);rs.push_back(i);}returnmake_pair(aux,ps);}};/**
* @brief Auxiliary Tree
*/