版权声明:本文为博主原创文章,未经博主允许必须转载。 https://blog.csdn.net/C20181220_xiang_m_y/article/details/88673097
板题,维护add,mul,siz,val,sum。
下传的时候优先乘法。
Code:
#include<cstdio>
#include<cctype>
#include<cstring>
#include<map>
#include<algorithm>
#define maxn 100005
using namespace std;
inline void read(int &a){
char c;while(!isdigit(c=getchar()));
for(a=c-'0';isdigit(c=getchar());a=a*10+c-'0');
}
inline void print(int a){
if(a>=10) print(a/10);
putchar(a%10+48);
}
const int mod = 51061;
namespace LCT{
int ch[maxn][2],fa[maxn],add[maxn],mul[maxn],sum[maxn],siz[maxn],v[maxn];
bool rev[maxn];
#define il inline
#define lc ch[x][0]
#define rc ch[x][1]
inline bool isc(int x){return ch[fa[x]][1]==x;}
il bool isr(int x){return ch[fa[x]][0]!=x&&ch[fa[x]][1]!=x;}
void upd_add(int x,int d){
if(!x) return;
sum[x]=(sum[x]+1ll*d*siz[x])%mod;
add[x]=(add[x]+d)%mod;
v[x]=(v[x]+d)%mod;
}
void upd_mul(int x,int d){
if(!x) return;
sum[x]=1ll*sum[x]*d%mod;
mul[x]=1ll*mul[x]*d%mod;
add[x]=1ll*add[x]*d%mod;
v[x]=1ll*v[x]*d%mod;
}
il void pd(int x){
if(rev[x]) swap(lc,rc),rev[x]=0,rev[lc]^=1,rev[rc]^=1;
if(mul[x]!=1) upd_mul(lc,mul[x]),upd_mul(rc,mul[x]),mul[x]=1;
if(add[x]) upd_add(lc,add[x]),upd_add(rc,add[x]),add[x]=0;
}
il void pdpath(int x){if(!isr(x)) pdpath(fa[x]);pd(x);}
il void upd(int x){
sum[x]=(sum[lc]+sum[rc]+v[x])%mod;
siz[x]=siz[lc]+siz[rc]+1;
}
il void rot(int x){
int y=fa[x],z=fa[y],c=isc(x);
if(!isr(y)) ch[z][ch[z][1]==y]=x;
(ch[y][c]=ch[x][!c])&&(fa[ch[y][c]]=y);
fa[ch[x][!c]=y]=x,fa[x]=z;
upd(y),upd(x);
}
il void splay(int x){
pdpath(x);
for(;!isr(x);rot(x))
if(!isr(fa[x])) rot(isc(fa[x])==isc(x)?fa[x]:x);
}
il int access(int x,int y=0){
for(;x;x=fa[y=x]) splay(x),rc=y,upd(x);
return y;
}
il void bert(int x){
access(x),splay(x),rev[x]^=1;
}
il void link(int x,int y){
bert(x),fa[x]=y;
}
il void cut(int x,int y){
bert(x),access(y),splay(y);
fa[x]=ch[y][0]=0;
upd(y);
}
il int split(int x,int y){
bert(x),access(y),splay(y);
return y;
}
il void modify_add(int x,int y,int d){upd_add(split(x,y),d);}
il void modify_mul(int x,int y,int d){upd_mul(split(x,y),d);}
il int qsum(int x,int y){return sum[split(x,y)];}
}
using namespace LCT;
int n,m,x,y,d;
char c;
int main()
{
read(n),read(m);
for(int i=1;i<=n;i++) siz[i]=mul[i]=sum[i]=v[i]=1;
for(int i=1;i<n;i++) read(x),read(y),link(x,y);
while(m--){
c=getchar(),read(x),read(y);
if(c=='+') read(d),modify_add(x,y,d);
if(c=='*') read(d),modify_mul(x,y,d);
if(c=='/') print(qsum(x,y)),putchar('\n');
if(c=='-') cut(x,y),read(x),read(y),link(x,y);
}
}