链接
调了好久。。。
我平常写平衡树时 \(push\) \(tag\) 的操作都习惯把 \(rev\) 数组清零,但在 \(LCT\) 中不行,因为 \(rev\) 储存了节点间的父子关系,直接清零会改变树的结构。
\(\frak{code}\)
#include<bits/stdc++.h>
#define IL inline
#define LL long long
#define ls(x) ch[x][0]
#define rs(x) ch[x][1]
using namespace std;
const int N=1e5+3;
int n,m;
IL int in(){
char c;int f=1;
while((c=getchar())<'0'||c>'9')
if(c=='-') f=-1;
int x=c-'0';
while((c=getchar())>='0'&&c<='9')
x=x*10+c-'0';
return x*f;
}
struct LCT{
int fa[N],ch[N][2],rev[N],tag[N],col[N],lc[N],rc[N],sum[N];
IL int chk(int x){return rs(fa[x])==x;}
IL int noroot(int x){return ls(fa[x])==x||rs(fa[x])==x;}
IL void pushup(int x){
if(ls(x)) lc[x]=lc[ls(x)];else lc[x]=col[x];
if(rs(x)) rc[x]=rc[rs(x)];else rc[x]=col[x];
sum[x]=sum[ls(x)]+sum[rs(x)]+1;
if(ls(x)) sum[x]-=(col[x]==rc[ls(x)]);
if(rs(x)) sum[x]-=(col[x]==lc[rs(x)]);
}
IL void Rev(int x){rev[x]^=1,swap(ls(x),rs(x)),swap(lc[x],rc[x]);}
IL void Tag(int x,int v){tag[x]=col[x]=lc[x]=rc[x]=v,sum[x]=1;}
IL void pushdown(int x){
if(tag[x]){
if(ls(x)) Tag(ls(x),tag[x]);
if(rs(x)) Tag(rs(x),tag[x]);
tag[x]=0;
}
if(rev[x]){
if(ls(x)) Rev(ls(x));
if(rs(x)) Rev(rs(x));
rev[x]=0;
}
}
IL void rotate(int x){
int y=fa[x],z=fa[y],k=chk(x),w=ch[x][k^1];
if(noroot(y)) ch[z][chk(y)]=x;
if(w) fa[w]=y;
fa[y]=x,fa[x]=z,ch[x][k^1]=y,ch[y][k]=w;
pushup(y),pushup(x);
}
void pushall(int x){
if(noroot(x)) pushall(fa[x]);
pushdown(x);
}
IL void splay(int x){
pushall(x);
while(noroot(x)){
int y=fa[x];
if(noroot(y))
rotate(chk(x)^chk(y)?x:y);
rotate(x);
}
}
IL void access(int x){for(int y=0;x;x=fa[y=x]) splay(x),rs(x)=y,pushup(x);}
IL void makeroot(int x){access(x),splay(x),Rev(x);}
IL void split(int x,int y){makeroot(x),access(y),splay(y);}
IL void link(int x,int y){makeroot(x),fa[x]=y;}
}T;
int main()
{
char op[5];int x,y,z;
n=in(),m=in();
for(int i=1;i<=n;++i) T.col[i]=T.lc[i]=T.rc[i]=in(),T.sum[i]=1;
for(int i=1;i<n;++i) T.link(in(),in());
while(m--){
scanf("%s",op+1),x=in(),y=in();
if(op[1]=='Q') T.split(x,y),printf("%d\n",T.sum[y]);
else T.split(x,y),T.Tag(y,in());
}
return 0;
}
附上一年多前写的树剖代码(那时真的 \(naive\),代码好笨拙啊qwq
#include<bits/stdc++.h>
using namespace std;
const int maxn=1e5+10;
struct hh{
int next,to;
}lin[maxn<<1];
struct kk{
int left,right,num;
}a[maxn<<2];
int siz[maxn],fa[maxn],d[maxn],son[maxn],numm[maxn];
int top[maxn],seg[maxn],rev[maxn],fir[maxn],nn,n,m,ans,z,last[4][3];
char sign[maxn<<2];
inline int read()
{
char c;
while((c=getchar())<'0'||c>'9');
int x=c-'0';
while((c=getchar())>='0'&&c<='9')
x=x*10+c-'0';
return x;
}
void init(int x,int y)
{
lin[++nn].next=fir[x];
fir[x]=nn;
lin[nn].to=y;
}
void dfs1(int s,int f)
{
int u;
siz[s]=1,d[s]=d[f]+1,fa[s]=f;
for(int i=fir[s];i;i=lin[i].next)
{
u=lin[i].to;
if(u!=f){
dfs1(u,s);
siz[s]+=siz[u];
if(siz[u]>siz[son[s]]) son[s]=u;
}
}
}
void dfs2(int f)
{
int u=son[f];
if(u){
seg[u]=++seg[0];
rev[seg[0]]=u;
top[u]=top[f];
dfs2(u);
}
for(int i=fir[f];i;i=lin[i].next)
{
u=lin[i].to;
if(!top[u]){
seg[u]=++seg[0];
rev[seg[0]]=u;
top[u]=u;
dfs2(u);
}
}
}
void pd(int k)
{
a[k].left=a[k<<1].left,a[k].right=a[k<<1|1].right;
a[k].num=a[k<<1].num+a[k<<1|1].num;
if(a[k<<1].right==a[k<<1|1].left) --a[k].num;
}
void build(int k,int l,int r)
{
if(l==r){
a[k].left=a[k].right=numm[rev[l]],a[k].num=1;return;
}
int mid=l+r>>1;
build(k<<1,l,mid),build(k<<1|1,mid+1,r);
pd(k);
}
void push(int k)
{
a[k<<1].left=a[k<<1].right=a[k<<1|1].left=a[k<<1|1].right=a[k].left;
a[k<<1].num=a[k<<1|1].num=1;sign[k]=0,sign[k<<1]=sign[k<<1|1]=1;
}
void query(int k,int l,int r,int ll,int rr)
{
if(l>=ll&&r<=rr){
ans+=a[k].num;
if(l==ll) last[3][nn]=a[k].left;//fx
if(r==rr) last[2][nn]=a[k].right;//x
return;
}
if(sign[k]) push(k);
int mid=l+r>>1;
if(mid>=ll) query(k<<1,l,mid,ll,rr);
if(mid<rr) query(k<<1|1,mid+1,r,ll,rr);
if(mid>=ll&&mid<rr&&a[k<<1].right==a[k<<1|1].left) ans--;
}
void change(int k,int l,int r,int ll,int rr)
{
if(l>=ll&&r<=rr){
a[k].num=1,a[k].left=a[k].right=z,sign[k]=1;return;
}
if(sign[k]) push(k);
int mid=l+r>>1;
if(mid>=ll) change(k<<1,l,mid,ll,rr);
if(mid<rr) change(k<<1|1,mid+1,r,ll,rr);
pd(k);
}
void ask(int x,int y)
{
int fx=top[x],fy=top[y];
last[1][1]=last[1][2]=-1;
while(fx!=fy)
{
if(d[fx]>d[fy]){
nn=1,query(1,1,seg[0],seg[fx],seg[x]);
if(last[1][1]==last[2][1]) ans--;
last[1][1]=last[3][1];
x=fa[fx],fx=top[x];
}
else{
nn=2,query(1,1,seg[0],seg[fy],seg[y]);
if(last[1][2]==last[2][2]) ans--;
last[1][2]=last[3][2];
y=fa[fy],fy=top[y];
}
}
nn=2;
if(d[x]>d[y]) swap(x,y),nn=1;
query(1,1,seg[0],seg[x],seg[y]);
if(last[1][nn]==last[2][nn]) ans--;
if(last[3][nn]==last[1][3-nn]) ans--;
}
void solve(int x,int y)
{
int fx=top[x],fy=top[y];
while(fx!=fy){
if(d[fx]<d[fy]) swap(x,y),swap(fx,fy);
change(1,1,seg[0],seg[fx],seg[x]);
x=fa[fx],fx=top[x];
}
if(d[x]>d[y]) swap(x,y);
change(1,1,seg[0],seg[x],seg[y]);
}
int main()
{
int x,y;
char flag[5];
n=read(),m=read();
for(int i=1;i<=n;++i) numm[i]=read();
for(int i=1;i<n;++i)
{
x=read(),y=read();
init(x,y),init(y,x);
}
dfs1(1,0),seg[0]=seg[1]=rev[1]=top[1]=1,dfs2(1),build(1,1,seg[0]);
while(m--)
{
scanf("%s",flag);
if(flag[0]=='Q'){
x=read(),y=read(),ans=0,ask(x,y),printf("%d\n",ans);
}
else{
x=read(),y=read(),z=read(),solve(x,y);
}
}
return 0;
}