数组版(kuangbin):
#include<iostream>
#include<cstdio>
#include<string>
#include<cstring>
#include<vector>
#include<cmath>
#include<queue>
#include<stack>
#include<map>
#include<set>
#include<algorithm>
using namespace std;
const int maxn=300010;
const int INF=1000000000;
struct Edge
{
int v,next;
}edge[maxn*2];
int head[maxn],tot;
void add_edge(int u,int v)
{
edge[tot].v=v;
edge[tot].next=head[u];
head[u]=tot++;
}
struct LCT
{
int ch[maxn][2],pre[maxn],key[maxn];
int add[maxn],rev[maxn],maxv[maxn];
bool rt[maxn];
void dfs(int u)
{
for(int i=head[u];i!=-1;i=edge[i].next)
{
int v=edge[i].v;
if(pre[v]!=0)continue;
pre[v]=u;
dfs(v);
}
}
void update_add(int r,int d)
{
if(!r)return ;
key[r]+=d;
add[r]+=d;
maxv[r]+=d;
}
void update_rev(int r)
{
if(!r)return;
swap(ch[r][0],ch[r][1]);
rev[r]^=1;
}
void pushdown(int r)
{
if(add[r])
{
update_add(ch[r][0],add[r]);
update_add(ch[r][1],add[r]);
add[r]=0;
}
if(rev[r])
{
update_rev(ch[r][1]);
update_rev(ch[r][0]);
rev[r]=0;
}
}
void pushup(int r)
{
maxv[r]=max(max(maxv[ch[r][0]],maxv[ch[r][1]]),key[r]);
}
void rotate(int x)
{
int y=pre[x],kind=ch[y][1]==x;
ch[y][kind]=ch[x][!kind];
pre[ch[y][kind]]=y;
pre[x]=pre[y];
pre[y]=x;
ch[x][!kind]=y;
if(rt[y])rt[y]=false,rt[x]=true;
else ch[pre[x]][ch[pre[x]][1]==y]=x;
pushup(y);
}
//将根节点到r的路径上的所有及诶单的标记下方
void P(int r)
{
if(!rt[r])P(pre[r]);
pushdown(r);
}
void Splay(int r)
{
P(r);
while(!rt[r])
{
int f=pre[r],ff=pre[f];
if(rt[f])rotate(r);
else if((ch[ff][1]==f)==(ch[f][1]==r))
rotate(f),rotate(r);
else rotate(r),rotate(r);
}
pushup(r);
}
int Access(int x)
{
int y=0;
for(;x;x=pre[y=x])
{
Splay(x);
rt[ch[x][1]]=true,rt[ch[x][1]=y]=false;
pushup(x);
}
return y;
}
int getroot(int x)
{
Access(x);
Splay(x);
while (ch[x][0])
x = ch[x][0];
return x;
}
//判断是否同根
bool judge(int u,int v)
{
while(pre[u])u=pre[u];
while(pre[v])v=pre[v];
return u==v;
}
//将r变成他所在根
void mroot(int r)
{
Access(r);
Splay(r);
update_rev(r);
}
//调用后u是原来u和v的lca,v和ch[u][1]分别存折lca的两个儿子
void lca(int &u,int &v)
{
Access(v),v=0;
while(u)
{
Splay(u);
if(!pre[u])return;
rt[ch[u][1]]=true;
rt[ch[u][1]=v]=false;
pushup(u);
u=pre[v=u];
}
}
//将u合并到v上
void link(int u,int v)
{
mroot(u);
pre[u]=v;
}
//将v和他的父节点分离
void cut(int v)
{
//mroot(v);
Access(v);
Splay(v);
pre[ch[v][0]]=0;
pre[v]=0;
rt[ch[v][0]]=true;
ch[v][0]=0;
pushup(v);
}
void init()
{
memset(head,-1,sizeof(head));
memset(pre,0,sizeof(pre));
memset(ch,0,sizeof(ch));
memset(rev,0,sizeof(rev));
memset(add,0,sizeof(add));
for(int i=0;i<=N;i++)rt[i]=true;
maxv[0]=-INF;
}
};
指针版(动态树LCT总结):
struct Node
{
Node *p,*ch[2];
int mx,rev,val,add;
}node[maxn],*cur,*null;
Node *NewNode(int key)
{
cur->p=cur->ch[0]=cur->ch[1]=null;
cur->mx=cur->val=key;
cur->rev=0;
return cur++;
}
void init()
{
null=node;
null->p=null->ch[0]=null->ch[1]=null;
null->mx=null->val=-INF;
null->add=0;
null->rev=0;
cur=node+1;
}
struct LCT
{
bool isroot(Node *x)
{
return x==null||x->p->ch[0]!=x&&x->p->ch[1]!=x;
}
void pushup(Node *x)
{
x->mx=max(x->val,max(x->ch[0]->mx,x->ch[1]->mx));
}
void pushdown(Node *x)
{
if(x==null)return;
if(x->rev)
{
x->rev=0;
if(x->ch[0]!=null)x->ch[0]->rev^=1;
if(x->ch[1]!=null)x->ch[1]->rev^=1;
swap(x->ch[0],x->ch[1]);
}
if(x->add)
{
if(x->ch[0]!=null) x->ch[0]->add+=x->add,x->ch[0]->val+=x->add,x->ch[0]->mx+=x->add;
if(x->ch[1]!=null) x->ch[1]->add+=x->add,x->ch[1]->val+=x->add,x->ch[1]->mx+=x->add;
x->add=0;
}
}
void rotate(Node *x,int f)
{
if(isroot(x)) return;
Node *y=x->p;
y->ch[!f]=x->ch[f];
x->p=y->p;
if(x->ch[f]!=null) x->ch[f]->p=y;
if(y!=null)
{
if(y==y->p->ch[1]) y->p->ch[1]=x;
else if(y==y->p->ch[0]) y->p->ch[0]=x;
}
x->ch[f]=y;
y->p=x;
pushup(y);
}
void Splay(Node *x)
{
static Node *sta[maxn];
int top=1;
sta[0]=x;
for(Node *y=x;!isroot(y);y=y->p)
sta[top++]=y->p;
while (top) pushdown(sta[--top]);
while (!isroot(x))
{
Node *y=x->p;
if(isroot(y)) rotate(x,x==y->ch[0]);
else
{
int f=y->p->ch[0]==y;
if(y->ch[f]==x) rotate(x,!f);
else rotate(y,f);
rotate(x,f);
}
}
pushup(x);
}
Node *access(Node *u)
{
Node *v=null;
while (u!=null)
{
Splay(u);
v->p=u;
u->ch[1]=v;
pushup(u);
v=u;
u=u->p;
}
return v;
}
Node *link(Node *u,Node *v)//合并
{
access(u);
Splay(u);
u->rev=1;
u->p=v;
}
Node *cut(Node *u)//分离
{
access(u);
Splay(u);
u->ch[0]=u->ch[0]->p=null;
pushup(u);
}
void changeroot(Node *u)
{
access(u)->rev^=1;
}
Node *getroot(Node *u)//找根
{
access(u);
Splay(u);
while (u->ch[0]!=null) u=u->ch[0];
Splay(u);
return u;
}
bool judge(Node *u,Node *v)//判断是否在同一子树
{
while (u->p!=null) u=u->p;
while (v->p!=null) v=v->p;
return u==v;
}
}tree;