#pragma once
/**
* Author: Teetat T.
* Date: 2024-05-19
* Description: Link Cut Tree Base.
* Usage:
* evert(u): make u be the root of the tree.
* link(u,v): attach u to v.
* cut(u,v): remove edge between u and v.
* get_root(u): get the root of the tree containing u.
* lca(u,v): get the lowest common ancestor of u and v.
* fold(u,v): get the value of the path from u to v.
*/template<classSplay>structLinkCutTreeBase:Splay{usingNode=typenameSplay::Node;usingPtr=Node*;usingT=typenameNode::value_type;Ptrexpose(Ptrt){Ptrpc=nullptr;// preferred childfor(Ptrcur=t;cur;cur=cur->p){this->splay(cur);cur->r=pc;this->pull(cur);pc=cur;}this->splay(t);returnpc;}voidevert(Ptrt){// make t be the root of the treeexpose(t);this->toggle(t);this->push(t);}voidlink(Ptru,Ptrv){// attach u to vevert(u);expose(v);u->p=v;}voidcut(Ptru,Ptrv){// cut edge between u and vevert(u);expose(v);assert(u->p==v);v->l=u->p=nullptr;this->pull(v);}Ptrget_root(Ptrt){expose(t);while(t->l)this->push(t),t=t->l;this->splay(t);returnt;}Ptrlca(Ptru,Ptrv){if(get_root(u)!=get_root(v))returnnullptr;expose(u);returnexpose(v);}voidset_val(Ptrt,constT&val){this->evert(t);t->val=val;this->pull(t);}Tget_val(Ptrt){this->evert(t);returnt->val;}Tfold(Ptru,Ptrv){evert(u);expose(v);returnv->sum;}};
#line 2 "data-structure/link-cut-tree/link-cut-tree-base.hpp"
/**
* Author: Teetat T.
* Date: 2024-05-19
* Description: Link Cut Tree Base.
* Usage:
* evert(u): make u be the root of the tree.
* link(u,v): attach u to v.
* cut(u,v): remove edge between u and v.
* get_root(u): get the root of the tree containing u.
* lca(u,v): get the lowest common ancestor of u and v.
* fold(u,v): get the value of the path from u to v.
*/template<classSplay>structLinkCutTreeBase:Splay{usingNode=typenameSplay::Node;usingPtr=Node*;usingT=typenameNode::value_type;Ptrexpose(Ptrt){Ptrpc=nullptr;// preferred childfor(Ptrcur=t;cur;cur=cur->p){this->splay(cur);cur->r=pc;this->pull(cur);pc=cur;}this->splay(t);returnpc;}voidevert(Ptrt){// make t be the root of the treeexpose(t);this->toggle(t);this->push(t);}voidlink(Ptru,Ptrv){// attach u to vevert(u);expose(v);u->p=v;}voidcut(Ptru,Ptrv){// cut edge between u and vevert(u);expose(v);assert(u->p==v);v->l=u->p=nullptr;this->pull(v);}Ptrget_root(Ptrt){expose(t);while(t->l)this->push(t),t=t->l;this->splay(t);returnt;}Ptrlca(Ptru,Ptrv){if(get_root(u)!=get_root(v))returnnullptr;expose(u);returnexpose(v);}voidset_val(Ptrt,constT&val){this->evert(t);t->val=val;this->pull(t);}Tget_val(Ptrt){this->evert(t);returnt->val;}Tfold(Ptru,Ptrv){evert(u);expose(v);returnv->sum;}};