template/ShinriiTin/link-cut-tree
const int max_N=1e5;//最大的节点数
namespace Link_Cut_Tree{
#define rep(d) for(int d=0;d<2;++d)
typedef struct node*star;
star null,tail,rt[max_N+1];
struct node{
int sz;
bool rev_flag;
star p,ch[2];
inline void update(){
sz=ch[0]->sz+1+ch[1]->sz;
}
inline void putdown(){
if(rev_flag){
std::swap(ch[0],ch[1]);
ch[0]->rev_flag^=1,ch[1]->rev_flag^=1;
rev_flag=0;
}
}
inline int dir(){
rep(d)if(p->ch[d]==this)return d;
return -1;
}
inline void set_ch(star x,int d){
if(~d)ch[d]=x;
if(x!=null)x->p=this;
}
}pool[max_N+1];
inline star init_null(){
star x=tail++;
x->sz=x->rev_flag=0;
x->ch[0]=x->ch[1]=x->p=x;
return x;
}
inline star new_node(){
star x=tail++;
x->sz=1,x->rev_flag=0;
x->ch[0]=x->ch[1]=x->p=null;
return x;
}
inline void rot(star x){
register int d,d1;
star y=x->p;
d=x->dir(),d1=y->dir();
y->p->set_ch(x,d1);
y->set_ch(x->ch[d^1],d),y->update();
x->set_ch(y,d^1);
}
void pd(star x){
if(~x->dir())pd(x->p); x->putdown();
}
inline void splay(star x){
register int d,d1;
for(pd(x);~(d=x->dir());rot(x))if(~(d1=x->p->dir()))rot((d^d1)?x:x->p);
x->update();
}
inline void access(star x){
register star y,rch;
for(y=x,rch=null;y!=null;rch=y,y=y->p)splay(y),y->set_ch(rch,1),y->update();
splay(x);
}
inline void evert(star x){
access(x),x->rev_flag^=1;
}
inline star get_path(star x,star y){//返回包含x到y的路径上所有点的splay的根
return evert(x),access(y),y;
}
inline void link(star x,star y){//添加一条x到y的边,需要保证添加后仍是树结构
evert(x),x->p=y;
}
inline void cut(star x,star y){//断开x到y之间的边,需要保证这条边存在
evert(x),access(y);
x->p=null,y->set_ch(null,0),y->update();
}
inline void init(int n){//初始化n个点的森林
tail=pool,null=init_null();
for(int i=1;i<=n;++i)rt[i]=new_node();
}
};
支持链翻转的LCT
namespace Splay{
typedef struct node*star;
star null,tail;
inline star new_node(int val);
struct node{
int siz,val,add;
bool rev;
star ch[2],p;
inline int d(){
if(this==null)return -1;
rpt(i,0,1)if(p->ch[i]==this)return i;
return -1;
}
inline void set_ch(star x,int d){
if(this!=null&&~d)ch[d]=x;
if(x!=null)x->p=this;
}
inline void add_it(int a){
if(this==null)return;
val+=a,add+=a;
}
inline void update(){
siz=ch[0]->siz+1+ch[1]->siz;
}
inline void push_down(){
if(rev){
std::swap(ch[0],ch[1]);
ch[0]->rev^=1,ch[1]->rev^=1;
rev=0;
}
if(add){
ch[0]->add_it(add),ch[1]->add_it(add);
add=0;
}
}
}pool[max_N+21];
inline void rot(star x){
star y=x->p;
int d=x->d(),d1=y->d();
y->p->set_ch(x,d1);
y->set_ch(x->ch[d^1],d),y->update();
x->set_ch(y,d^1);
}
void pd(star x){
if(~x->d())pd(x->p);
x->push_down();
}
inline void splay(star x){
pd(x);
for(int d,d1;~(d=x->d());rot(x))
if(~(d1=x->p->d()))rot(d^d1?x:x->p);
x->update();
}
star kth(star x,int k){
x->push_down();
int rk=x->ch[0]->siz+1;
if(rk==k)return x;
if(rk>k)return kth(x->ch[0],k);
return kth(x->ch[1],k-rk);
}
inline star new_node(int val){
star x=tail++;
x->ch[0]=x->ch[1]=x->p=null;
x->val=val,x->siz=1;
x->add=x->rev=0;
return x;
}
inline void init(){
tail=pool;
null=tail++;
null->ch[0]=null->ch[1]=null->p=null;
null->val=null->siz=null->add=null->rev=0;
}
};
namespace LCT{
typedef struct node*star;
star null,tail;
struct node{
int siz;
bool rev;
star ch[2],p;
Splay::star link;
inline int d(){
if(this==null)return -1;
rpt(i,0,1)if(p->ch[i]==this)return i;
return -1;
}
inline void set_ch(star x,int d){
if(this!=null&&~d)ch[d]=x;
if(x!=null)x->p=this;
}
inline void maintain(){
push_down();
int rk=ch[0]->siz+1;
link=Splay::kth(link,rk);
Splay::splay(link);
}
inline void update(){
siz=ch[0]->siz+1+ch[1]->siz;
}
inline void push_down(){
if(rev){
std::swap(ch[0],ch[1]);
ch[0]->rev^=1,ch[1]->rev^=1;
rev=0;
}
}
}pool[max_N+21];
inline void rot(star x){
star y=x->p;
int d=x->d(),d1=y->d();
y->p->set_ch(x,d1);
y->set_ch(x->ch[d^1],d),y->update();
x->set_ch(y,d^1);
}
void pd(star x,star&top){
if(~x->d())pd(x->p,top);
else top=x;
x->push_down();
}
inline void splay(star x){
star top;
pd(x,top),x->link=top->link;
for(int d,d1;~(d=x->d());rot(x))
if(~(d1=x->p->d()))rot(d^d1?x:x->p);
x->update();
}
inline void change_rch(star x,star y){
x->maintain();
x->ch[1]->link=x->link->ch[1];
x->ch[1]->link->p=Splay::null;
x->set_ch(y,1),x->link->set_ch(y->link,1);
x->update(),x->link->update();
}
inline void Access(star x){
star rch=null;
for(star y=x;y!=null;rch=y,y=y->p)splay(y),change_rch(y,rch);
splay(x);
}
inline void Evert(star x){
Access(x),x->rev^=1,x->link->rev^=1;
}
inline star get_path(star x,star y){
return Evert(x),Access(y),y;
}
inline int query(star x){
Evert(x),Access(x);
return x->link->val;
}
inline star new_node(int val){
star x=tail++;
x->ch[0]=x->ch[1]=x->p=null;
x->siz=1,x->rev=0;
x->link=Splay::new_node(val);
return x;
}
inline void init(){
Splay::init();
tail=pool;
null=tail++;
null->ch[0]=null->ch[1]=null->p=null;
null->link=Splay::null;
null->siz=null->rev=0;
}
};