LCT 模板
有些操作确实可以省略,如link, cut, modify和access操作,都可以不update;而findroot函数可以不pushdown。不过原因不明,自己并没有想明白,所以自己写的时候还是该加就加,不要卡那些微不足道的常数。
#include<bits/stdc++.h>
#define RG register
#define R register int
#define I inline
#define ll long long
using namespace std;
const int N=1e5+3;
struct node
{
int v,sm;
int son[2],fa;
bool rev;
};
node t[N];
int q[N],tq;
I bool isroot(int x)
{
RG node &p=t[t[x].fa];
return x!=p.son[0]&&x!=p.son[1];
}
I bool getw(int x){return t[t[x].fa].son[1]==x;}
I void pushdown(int x)
{
if(!t[x].rev)return;
R &ls=t[x].son[0],&rs=t[x].son[1];
t[x].rev=0;
t[ls].rev^=1;t[rs].rev^=1;
swap(ls,rs);
}
I void update(int x)
{
RG node &p=t[x];
p.sm=p.v^t[p.son[0]].sm^t[p.son[1]].sm;
}
I void rotate(int x)
{
const R y=t[x].fa,z=t[y].fa;
const RG bool w=getw(x);
R &s=t[x].son[!w];
t[x].fa=z;if(!isroot(y))t[z].son[getw(y)]=x;
t[s].fa=y;t[y].son[w]=s;
t[y].fa=x;s=y;
update(y);
}
void splay(int x)
{
q[tq=1]=x;
for(R p=x;!isroot(p);p=t[p].fa)q[++tq]=t[p].fa;
for(;tq;tq--)pushdown(q[tq]);
for(R y;!isroot(x);rotate(x))
if(!isroot(y=t[x].fa))rotate(getw(x)==getw(y)?y:x);
update(x);
}
void access(int x)
{
for(R y=0;x;y=x,x=t[x].fa)
{
splay(x);
t[x].son[1]=y;
// update(x);
}
}
void makeroot(int x)
{
access(x);splay(x);
t[x].rev^=1;
}
int findroot(int x)
{
access(x);splay(x);
while(t[x].son[0])/*pushdown(x),*/x=t[x].son[0];
return splay(x),x;
}
void split(int x,int y)
{
makeroot(x);
access(y);
splay(y);
}
void link(int x,int y)
{
makeroot(y);
if(findroot(x)==y)return;
t[y].fa=x;
}
void cut(int x,int y)
{
split(x,y);
if(t[y].son[0]!=x||t[x].son[1])return;
t[y].son[0]=t[x].fa=0;
// update(y);
}
void modify(int x,int v)
{
// access(x);
splay(x);
t[x].v=v;
// update(x);
}
int main()
{
int n,m;
scanf("%d%d",&n,&m);
for(R i=1;i<=n;i++)scanf("%d",&t[i].v);
for(R i=1;i<=m;i++)
{
int op,x,y;
scanf("%d%d%d",&op,&x,&y);
if(op==0)split(x,y),printf("%d\n",t[y].sm);
else if(op==1)link(x,y);
else if(op==2)cut(x,y);
else modify(x,y);
}
return 0;
}
浙公网安备 33010602011771号