Luogu1501 [国家集训队]Tree II
https://www.luogu.com.cn/problem/P1501
\(LCT\)
注意标记的下放,需要记住一个原则
当该节点被打上标记时,该节点的值需要同时更新
下放标记时直接传给儿子,这时已经不能更新自己了
采取边更新边下放的方式到处都是锅
#include<cstdio>
#include<algorithm>
#include<iostream>
#define N 100005
#define ls(x) a[x].ch[0]
#define rs(x) a[x].ch[1]
#define fa(x) a[x].f
#define v(x) a[x].val
#define s(x) a[x].sz
#define ans(x) a[x].Sum
#define tag1(x) a[x].tag_add
#define tag2(x) a[x].tag_muti
#define tag(x) a[x].tag_reverse
#define id(x) (ls(fa(x))==x?0:1)
#define ll long long
using namespace std;
char cc;
int x,y,x2,y2,n,m,q[N];
ll c;
ll p=51061;
struct node
{
int ch[2],f,tag_reverse;
ll sz,val,Sum,tag_add,tag_muti;
}a[N];
void update(int x)
{
s(x)=s(ls(x))+s(rs(x))+1;
ans(x)=(ans(ls(x))+ans(rs(x))+v(x))%p;
}
void push_add(int x,ll y)
{
v(x)=(v(x)+y)%p;
ans(x)=(ans(x)+s(x)*y)%p;
tag1(x)=(tag1(x)+y)%p;
}
void push_mul(int x,ll y)
{
v(x)=v(x)*y%p;
ans(x)=ans(x)*y%p;
tag1(x)=tag1(x)*y%p;
tag2(x)=tag2(x)*y%p;
}
void push_rev(int x)
{
tag(x)^=1;
swap(ls(x),rs(x));
}
void pushdown(int x)
{
if (tag(x))
{
if (ls(x))
push_rev(ls(x));
if (rs(x))
push_rev(rs(x));
tag(x)=0;
}
if (tag2(x)!=1)
{
if (ls(x))
push_mul(ls(x),tag2(x));
if (rs(x))
push_mul(rs(x),tag2(x));
tag2(x)=1;
}
if (tag1(x))
{
if (ls(x))
push_add(ls(x),tag1(x));
if (rs(x))
push_add(rs(x),tag1(x));
tag1(x)=0;
}
}
bool isrt(int x)
{
return ls(fa(x))!=x && rs(fa(x))!=x;
}
void connect(int x,int F,int son)
{
fa(x)=F;
a[F].ch[son]=x;
}
void rot(int x)
{
int y=fa(x),r=fa(y);
int yson=id(x),rson=id(y);
if (isrt(y))
fa(x)=r; else
connect(x,r,rson);
connect(a[x].ch[yson^1],y,yson);
connect(y,x,yson^1);
update(y),update(x);
}
void splay(int x)
{
int g=x,k=0;
q[++k]=g;
while (!isrt(g))
g=fa(g),q[++k]=g;
while (k)
pushdown(q[k--]);
while (!isrt(x))
{
int y=fa(x);
if (isrt(y))
rot(x); else
if (id(x)==id(y))
rot(y),rot(x); else
rot(x),rot(x);
}
}
void access(int x)
{
for (int y=0;x;y=x,x=fa(x))
splay(x),rs(x)=y,update(x);
}
void makeroot(int x)
{
access(x);
splay(x);
push_rev(x);
}
void split(int x,int y)
{
makeroot(x);
access(y);
splay(y);
}
void link(int x,int y)
{
makeroot(x);
access(y);
splay(y);
fa(x)=y;
}
void cut(int x,int y)
{
makeroot(x);
access(y);
splay(y);
fa(x)=ls(y)=0;
update(y);
}
int main()
{
scanf("%d%d",&n,&m);
for (int i=1;i<=n;i++)
v(i)=ans(i)=1,s(i)=1,tag1(i)=0,tag2(i)=1;
for (int i=1;i<n;i++)
{
scanf("%d%d",&x,&y);
link(x,y);
}
for (int i=1;i<=m;i++)
{
cc=getchar();
while (cc!='+' && cc!='-' && cc!='*' && cc!='/')
cc=getchar();
if (cc=='+')
{
scanf("%d%d%lld",&x,&y,&c);
split(x,y);
push_add(y,c);
} else
if (cc=='-')
{
scanf("%d%d%d%d",&x,&y,&x2,&y2);
cut(x,y);
link(x2,y2);
} else
if (cc=='*')
{
scanf("%d%d%lld",&x,&y,&c);
split(x,y);
push_mul(y,c);
} else
{
scanf("%d%d",&x,&y);
split(x,y);
printf("%lld\n",ans(y));
}
}
return 0;
}