#ifndef AFGR_LCA
#define AFGR_LCA
#include"../data_structure/sparse-table.hpp"
#include<vector>// requires a previous graph definition.classLCAImpl{private:std::vector<int>dfn,seq;// dfn and seq are (internally) zero indexed.staticstd::vector<int>d;structEulerTourInfo{intval;EulerTourInfo(void):val(0){}EulerTourInfo(intx):val(x){}EulerTourInfooperator+(EulerTourInfo&x){returnd[val]<d[x.val]?val:x.val;}};SparseTable<EulerTourInfo>lca;// 0 indexed.inlinevoid_dfs(intx,intfa){dfn[x]=seq.size();seq.push_back(x),d[x]=d[fa]+1;for(auto&y:G[x]){if(y==fa)continue;_dfs(y,x),seq.push_back(x);}}public:inlinevoidinit(intn,intrt=1){d.assign(n+1,0),dfn.assign(n+1,0);seq.clear(),_dfs(rt,0),lca.init(seq);}inlineintLCA(intu,intv){if(u==-1)returnv;if(v==-1)returnu;if(dfn[u]>dfn[v])std::swap(u,v);returnlca.query(dfn[u],dfn[v]).val;}inlineintdis(intu,intv){returnd[u]+d[v]-2*d[LCA(u,v)];}}LCA;std::vector<int>LCAImpl::d;structLCAInfo{intval;LCAInfo(void):val(-1){}template<classInitT>LCAInfo(InitTx){val=x;}LCAInfooperator+(LCAInfo&x){return{LCA.LCA(val,x.val)};}};// for range lca.#endif // AFGR_LCA
#line 1 "src/alfred/graph/lca.hpp"
#line 1 "src/alfred/data_structure/sparse-table.hpp"
#include<limits>
#include<numeric>
#include<vector>template<classT>structMaxInfo{Tval;MaxInfo(void){val=std::numeric_limits<T>::min();}template<classInitT>MaxInfo(InitTx){val=x;}MaxInfooperator+(MaxInfo&x){return{std::max(val,x.val)};}};template<classT>structMinInfo{Tval;MinInfo(void){val=std::numeric_limits<T>::max();}template<classInitT>MinInfo(InitTx){val=x;}MinInfooperator+(MinInfo&x){return{std::min(val,x.val)};}};template<classT>structGcdInfo{Tval;GcdInfo(void){val=T();}template<classInitT>GcdInfo(InitTx){val=x;}GcdInfooperator+(GcdInfo&x){#if __cplusplus >= 201703L
return{std::gcd(x.val,val)};#else
return{__gcd(x.val,val)};#endif
}};template<classT>classSparseTable{private:intn;std::vector<std::vector<T>>ST;public:SparseTable(void){}SparseTable(intN):n(N),ST(N,std::vector<T>(std::__lg(N)+1)){}template<classInitT>SparseTable(std::vector<InitT>&_init):SparseTable(_init.size()){init(_init,true);}template<classInitT>inlinevoidinit(std::vector<InitT>&_init,boolinternal=false){if(!internal){n=_init.size();ST.assign(n,std::vector<T>(std::__lg(n)+1));}for(inti=0;i<n;i++)ST[i][0]=T(_init[i]);for(inti=1;(1<<i)<=n;i++){for(intj=0;j+(1<<i)-1<n;j++){ST[j][i]=ST[j][i-1]+ST[j+(1<<(i-1))][i-1];}}}inlineTquery(intl,intr){// 0 basedif(l>r)returnT();intw=std::__lg(r-l+1);returnST[l][w]+ST[r-(1<<w)+1][w];}inlineTdisjoint_query(intl,intr){if(l>r)returnT();Tans=T();for(inti=std::__lg(r-l+1);i>=0;i--){if((1<<i)<=r-l+1){ans=ans+ST[l][i];l+=1<<i;}}returnans;}};#line 6 "src/alfred/graph/lca.hpp"
// requires a previous graph definition.classLCAImpl{private:std::vector<int>dfn,seq;// dfn and seq are (internally) zero indexed.staticstd::vector<int>d;structEulerTourInfo{intval;EulerTourInfo(void):val(0){}EulerTourInfo(intx):val(x){}EulerTourInfooperator+(EulerTourInfo&x){returnd[val]<d[x.val]?val:x.val;}};SparseTable<EulerTourInfo>lca;// 0 indexed.inlinevoid_dfs(intx,intfa){dfn[x]=seq.size();seq.push_back(x),d[x]=d[fa]+1;for(auto&y:G[x]){if(y==fa)continue;_dfs(y,x),seq.push_back(x);}}public:inlinevoidinit(intn,intrt=1){d.assign(n+1,0),dfn.assign(n+1,0);seq.clear(),_dfs(rt,0),lca.init(seq);}inlineintLCA(intu,intv){if(u==-1)returnv;if(v==-1)returnu;if(dfn[u]>dfn[v])std::swap(u,v);returnlca.query(dfn[u],dfn[v]).val;}inlineintdis(intu,intv){returnd[u]+d[v]-2*d[LCA(u,v)];}}LCA;std::vector<int>LCAImpl::d;structLCAInfo{intval;LCAInfo(void):val(-1){}template<classInitT>LCAInfo(InitTx){val=x;}LCAInfooperator+(LCAInfo&x){return{LCA.LCA(val,x.val)};}};// for range lca.