LCT(維護加乘標記)--luogu P1501 [國家集訓隊]Tree II
阿新 • • 發佈:2018-12-02
就是鏈上維護加和乘的標記,先乘後加
沒開long long wa到懷疑人生祭
#include<iostream>
#include<cstdio>
#include<algorithm>
#include<cstring>
#include<cmath>
#define N 100005
#define ls ch[x][0]
#define rs ch[x][1]
#define fa f[x]
#define LL long long
#define int LL
using namespace std;
inline int rd(){
int x=0,f=1;char c=' ';
while(c<'0' || c>'9') f=c=='-'?-1:1,c=getchar();
while(c<='9' && c>='0') x=x*10+c-'0',c=getchar();
return x*f;
}
int n,q;
int f[N],ch[N][2],rev[N],sum[N],tag1[N],tag2[N],val[N],siz[N];
const int mod=51061;
inline int get(int x){return ch[fa][1]==x;}
inline int isrt(int x){return ch[fa][0]!=x && ch[fa][1]!=x;}
inline void update(int x){sum[x]=(sum[ls]+sum[rs]+val[x])%mod;siz[x]=siz[ls]+siz[rs]+1;}
inline void rever(int x){rev[x]^=1;swap(ls,rs);}
inline void pushdown(int x){
if(rev[x]){
if(ls) rever(ls);
if(rs) rever(rs);
rev[x]=0;
}
if(tag2[x]!=1){
int t=tag2[x]; tag2[x]=1;
if(ls){
val[ls]=1LL*val[ls]*t%mod; tag1[ls]=1LL*tag1[ls]*t%mod; tag2[ls]=1LL*tag2[ls]*t%mod;
sum[ls]=1LL*sum[ls]*t%mod;
}
if(rs){
val[rs]=1LL*val[rs]*t%mod; tag1[rs]=1LL*tag1[rs]*t%mod; tag2[rs]=1LL*tag2[rs]*t%mod;
sum[rs]=1LL*sum[rs]*t%mod;
}
}
if(tag1[x]!=0){
int t=tag1[x]; tag1[x]=0;
if(ls){
(val[ls]+=t)%=mod; (tag1[ls]+=t)%=mod;
(sum[ls]+=1LL*t*siz[ls]%mod)%=mod;
}
if(rs){
(val[rs]+=t)%=mod; (tag1[rs]+=t)%=mod;
(sum[rs]+=1LL*t*siz[rs]%mod)%=mod;
}
}
// update(ls); update(rs);
}
void pushup(int x){if(!isrt(x)) pushup(fa);pushdown(x);}
inline void rotate(int x){
int old=f[x],oldf=f[old],wh=get(x);
if(!isrt(old)) ch[oldf][get(old)]=x;
ch[old][wh]=ch[x][wh^1]; f[ch[x][wh^1]]=old;
ch[x][wh^1]=old; f[x]=oldf; f[old]=x;
update(old); update(x);
}
inline void splay(int x){
pushup(x);
for(;!isrt(x);rotate(x))
if(!isrt(fa)) rotate(get(x)==get(fa)?fa:x);
}
inline void access(int x){
for(int y=0;x;y=x,x=fa) splay(x),rs=y,update(x);
}
inline void makeroot(int x){
access(x); splay(x); rever(x);
}
inline int findroot(int x){
access(x); splay(x);
while(ls) pushdown(x),x=ls; return x;
}
inline void split(int x,int y){
makeroot(x); access(y); splay(y);
}
inline void link(int x,int y){
if(findroot(x)==findroot(y)) return;
makeroot(x); f[x]=y;
}
inline void cut(int x,int y){
if(findroot(x)!=findroot(y)) return;
split(x,y);
if(ch[y][0]==x && !ch[x][1])
f[x]=ch[y][0]=0,update(y);
}
char s[10];
int x,y,z,p;
signed main(){
n=rd(); q=rd();
for(int i=1;i<=n;i++) val[i]=1,tag2[i]=1;
for(int i=1;i<n;i++){
x=rd(),y=rd();
link(x,y);
}
while(q--){
scanf("%s",s);
if(s[0]=='+'){
x=rd(),y=rd(),z=rd();
split(x,y); (sum[y]+=1LL*siz[y]*z%mod)%=mod;
(val[y]+=z%mod)%=mod; (tag1[y]+=z)%=mod;
}
if(s[0]=='-'){
x=rd(),y=rd(),z=rd(),p=rd();
cut(x,y); link(z,p);
}
if(s[0]=='*'){
x=rd(),y=rd(),z=rd();
split(x,y);
val[y]=1LL*val[y]*z%mod; sum[y]=1LL*sum[y]*z%mod;
tag1[y]=1LL*tag1[y]*z%mod; tag2[y]=1LL*tag2[y]*z%mod;
}
if(s[0]=='/'){
x=rd(),y=rd();
split(x,y); printf("%lld\n",sum[y]%mod);
}
}
return 0;
}