题目
我数据结构果然还是太菜了。
有多重标记的时候可以定义群(其实就是满足结合律结构体)来简化代码。
设 ( a , b ) (a,b) (a,b)可以使 ( v a l [ x ] , s u m [ x ] ) (val[x],sum[x]) (val[x],sum[x])变为 ( v a l [ x ] ∗ a + b , s u m [ x ] ∗ a + b ∗ s i z [ x ] ) (val[x]*a+b,sum[x]*a+b*siz[x]) (val[x]∗a+b,sum[x]∗a+b∗siz[x])
那么可以知道 ( a , b ) ∗ ( c , d ) = ( a c , b c + d ) (a,b)*(c,d)=(ac,bc+d) (a,b)∗(c,d)=(ac,bc+d)
重载运算符,美滋滋。
AC Code:
#include
#define maxn 100005
#define LL long long
#define mod 51061
using namespace std;
int n,q;
struct tag{
LL m,a;
tag(LL m=1,LL a=0):m(m),a(a){}
tag operator *(const tag &B)const{ return tag(1ll*m*B.m%mod,(1ll*a*B.m%mod+B.a)%mod); }
}lazy[maxn];
namespace LCT{
int fa[maxn],rev[maxn],ch[maxn][2],siz[maxn];
LL sum[maxn],val[maxn];
#define il inline
#define pa fa[x]
il int inr(int x){ return ch[pa][1]==x; }
il int isr(int x){ return ch[pa][0]!=x&&ch[pa][1]!=x; }
il void dtp(int x,tag v){
val[x] = (val[x] * v.m + v.a) % mod;
sum[x] = (sum[x] * v.m + v.a * siz[x]) % mod;
lazy[x] = lazy[x] * v;
}
il void dt(int x){
if(rev[x]){
swap(ch[x][0],ch[x][1]),rev[x]=0;
if(ch[x][0]) rev[ch[x][0]] ^= 1;
if(ch[x][1]) rev[ch[x][1]] ^= 1;
}
if(lazy[x].a!=0 || lazy[x].m!=1){
if(ch[x][0]) dtp(ch[x][0],lazy[x]);
if(ch[x][1]) dtp(ch[x][1],lazy[x]);
lazy[x] = tag(1,0);
}
}
il void dtpath(int x){ if(!isr(x)) dtpath(pa);dt(x); }
il void upd(int x){
sum[x] = (sum[ch[x][0]] + sum[ch[x][1]] + val[x]) % mod;
siz[x] = siz[ch[x][0]] + siz[ch[x][1]] + 1;
}
il void rot(int x){
int y=fa[x],z=fa[y],c=inr(x);
if(!isr(y)) ch[z][inr(y)]=x;
(ch[y][c]=ch[x][!c])&&(fa[ch[y][c]]=y);
fa[fa[ch[x][!c]=y]=x]=z;
upd(y),upd(x);
}
il void splay(int x){
dtpath(x);
for(;!isr(x);rot(x)){
if(!isr(pa)) rot(inr(x)==inr(pa)?pa:x);
}
}
il int access(int x,int y=0){
for(;x;x=fa[y=x]) splay(x),ch[x][1]=y,upd(x);
return y;
}
il void bert(int x){
access(x),splay(x),rev[x]^=1;
}
il int sert(int x){
access(x),splay(x);
for(;ch[x][0];)x=ch[x][0];
return x;
}
il void link(int x,int y){
bert(x);
if(sert(y)==x) return;
fa[x]=y;
}
il void cut(int x,int y){
bert(x),access(y),splay(y);
if(sert(y)!=x || siz[y]!=2) return;
fa[x]=ch[y][0]=0;
}
il int split(int x,int y){
bert(x),access(y),splay(y);
return y;
}
il void modify(int x,int y,tag c){
dtp(split(x,y),c);
}
il LL query(int x,int y){
return sum[split(x,y)];
}
}
int main(){
scanf("%d%d",&n,&q);
for(int i=1;i<=n;i++) LCT::modify(i,i,tag(1,1)),LCT::siz[i]=1;
for(int i=1,u,v;i<n;i++) scanf("%d%d",&u,&v),LCT::link(u,v);
char s[2];
for(int u,v,u1,v1;q--;){
scanf("%s",s);
if(s[0] == '+' || s[0]=='*'){
scanf("%d%d%d",&u,&v,&u1);
if(s[0] == '*') LCT::modify(u,v,tag(u1,0));
else LCT::modify(u,v,tag(1,u1));
}
else if(s[0]=='-'){
scanf("%d%d%d%d",&u,&v,&u1,&v1);
LCT::cut(u,v);
LCT::link(u1,v1);
}
else{
scanf("%d%d",&u,&v);
printf("%lld\n",LCT::query(u,v));
}
}
}