此题是bzoj2631
Lct真的是看一眼就懂的数据结构,Tarjan太强了
考虑轻重链剖分,我们可以将一条路径分成log个区间
而在Lct上,用splay来完成这一过程,每次将节点到根的路径强制变为重路径(Access操作)
这样,就可以很方便的来完成链上的查询和修改了
而换根,需要维护一个Reverse标记,每次
a
c
c
e
s
s
(
x
)
access(x)
access(x)之后将整颗splay翻转
反正不是很复杂辣,和线段树差不多吧
#include<stdio.h>
#include<string.h>
#include<algorithm>
#define M 51061
#define N 100010
#define son(x) (x==s[f[x]][1])
using namespace std;
int n,m,s[N][2],f[N],r[N];
unsigned v[N],w[N],a[N],t[N],sz[N];
inline int R(int x){
return s[f[x]][son(x)]==x;
}
inline void ps(int x){
sz[x]=(sz[s[x][0]]+sz[s[x][1]]+1)%M;
w[x]=(w[s[x][0]]+w[s[x][1]]+v[x])%M;
}
inline void add(int x,int d){
v[x]=(v[x]+d)%M; w[x]=(w[x]+d*sz[x])%M; a[x]=(a[x]+d)%M;
}
inline void mul(int x,int d){
v[x]=v[x]*d%M; w[x]=w[x]*d%M; t[x]=t[x]*d%M; a[x]=a[x]*d%M;
}
inline void rev(int x){
r[x]^=1; swap(s[x][0],s[x][1]);
}
inline void pd(int x){
if(r[x]){
rev(s[x][0]);
rev(s[x][1]);
r[x]=0;
}
if(t[x]!=1){
mul(s[x][0],t[x]);
mul(s[x][1],t[x]);
t[x]=1;
}
if(a[x]){
add(s[x][0],a[x]);
add(s[x][1],a[x]);
a[x]=0;
}
}
inline void rot(int x){
int p=f[x],g=f[p],d=son(x);
f[s[p][d]=s[x][!d]]=p;
if(R(p)) s[g][son(p)]=x; f[x]=g;
f[s[x][!d]=p]=x; ps(p); ps(x);
}
inline void pushdown(int x){
static int t,w[N];
for(w[t=1]=x;R(x);x=f[x]) w[++t]=f[x];
for(;t;--t) pd(w[t]);
}
inline void splay(int x){
pushdown(x);
for(int p;R(x);rot(x))
if(R(p=f[x])&&son(x)==son(p)) rot(p);
}
inline int access(int x,int y=0){
for(;x;y=x,x=f[x])
splay(x),s[x][1]=y,ps(x);
for(;s[y][0];y=s[y][0]);
return y;
}
inline void mkrt(int x){
access(x); splay(x); rev(x);
}
inline void link(int x,int y){
mkrt(x);
if(access(y)!=x) f[x]=y;
}
inline void cut(int x,int y){
mkrt(x);
if(access(y)==x){
splay(y);
if(f[x]==y && !s[x][1]){
f[x]=s[y][0]=0; ps(y);
}
}
}
int main(){
scanf("%d%d",&n,&m);
for (int i=1;i<=n;++i) v[i]=t[i]=1;
for(int x,y,i=1;i<n;++i){
scanf("%d%d",&x,&y); link(x,y);
}
char o[3];
for(int x,y,c;m--;){
scanf("%s%d%d",o,&x,&y);
if(*o=='+'){
scanf("%d",&c);
mkrt(x); access(y); splay(y); add(y,c);
} else if(*o=='-'){
cut(x,y);
scanf("%d%d",&x,&y);
link(x,y);
} else if(*o=='*'){
scanf("%d",&c);
mkrt(x); access(y); splay(y); mul(y,c);
} else {
mkrt(x); access(y); splay(y); printf("%d\n",w[y]);
}
}
}