宏定义
- #define pl a[p].ch[0]:LCT 中点 p 的左儿子。
- #define pr a[p].ch[1]:LCT 中点 p 的右儿子。
变量
- Tree a[p]:存储节点 p 信息的结构体。
- int a[p].ch[0/1]:点 p 的左/右儿子。
- int a[p].val:单点信息。
- int a[p].sum:以 p 为根的辅助子树的总信息。
- int a[p].rev:点 p 的翻转标记。
函数
- bool isroot(int p):判断点 p 是否是辅助树的根。
- void pushup(int p):由 p 的儿子向上传递信息。
- void pushrev(int p):翻转以 p 为根的辅助子树。
- void pushdown(int p):下放标记。
- int get(int p):得到 p 在其父亲下的儿子类型。
- void update(int p):下放 p 到其所在辅助树的根的标记。
- void rotate(int p):旋转 p 节点。
- void splay(int p):将 p 旋转到其辅助树的根节点。
- void access(int p):将 p 到原树根的路径改为实链。
- void makeroot(int p):将点 p 改为原树的根。
- int findroot(int p):找到 p 所在的原树的根节点。
- void split(int p,int q):拿出一颗维护 p 到 q 路径的 Splay。
- void link(int p,int q):连接 p 与 q,不一定保证 p 与 q 不连通。
- void cut(int p,int q):断开连接 p 与 q 的边,不保证这条边存在。
- void change(int p,int val):将点 p 的单点值修改为 val。
代码
#define pl a[p].ch[0]
#define pr a[p].ch[1]
struct LCT{
struct Tree{
int ch[2],fa;
int val,sum,rev;
}a[N];
bool isroot(int p){
return a[a[p].fa].ch[0]!=p&&a[a[p].fa].ch[1]!=p;
}
void pushup(int p){
a[p].sum=a[pl].sum^a[p].val^a[pr].sum;
}
void pushrev(int p){
swap(pl,pr);a[p].rev^=1;
}
void pushdown(int p){
if(a[p].rev){
if(pl)pushrev(pl);
if(pr)pushrev(pr);
a[p].rev=0;
}
}
int get(int p){
return a[a[p].fa].ch[1]==p;
}
void update(int p){
if(!isroot(p))update(a[p].fa);
pushdown(p);
}
void rotate(int p){
int fp=a[p].fa,ffp=a[fp].fa;
int ty=get(p);
if(!isroot(fp))a[ffp].ch[get(fp)]=p;a[p].fa=ffp;
a[fp].ch[ty]=a[p].ch[ty^1];
if(a[p].ch[ty^1])a[a[p].ch[ty^1]].fa=fp;
a[p].ch[ty^1]=fp;a[fp].fa=p;
pushup(fp);pushup(p);
}
void splay(int p){
update(p);
for(int fp;!isroot(p);rotate(p)){
fp=a[p].fa;
if(!isroot(fp))
rotate(get(fp)^get(p)?p:fp);
}
pushup(p);
}
void access(int p){
for(int q=0;p;p=a[q=p].fa)
splay(p),pr=q,pushup(p);
}
void makeroot(int p){
access(p);splay(p);pushrev(p);
}
int findroot(int p){
access(p);splay(p);
while(pl)pushdown(p),p=pl;
splay(p);return p;
}
void split(int p,int q){
makeroot(p);access(q);splay(q);
}
void link(int p,int q){
makeroot(p);if(p!=findroot(q))a[p].fa=q;
}
void cut(int p,int q){
makeroot(p);
if(findroot(q)==p&&a[q].fa==p&&!a[q].ch[0]){
a[q].fa=pr=0;
pushup(p);
}
}
void change(int p,int val){
splay(p);a[p].val=val;pushup(p);
}
}lct;