LCT板子题。
和线段树2的操作方法一样,先乘后加就行了。洛谷评分虚高
#include <iostream> #include <cstdio> #include <cstring> using namespace std; const int N=100005,mod=51061; int n,q,ch[N][2],fa[N];long long val[N];long long siz[N]; long long sum[N],add[N],mul[N]; bool rev[N]; bool is_rt(int x){return x!=ch[fa[x]][0]&&x!=ch[fa[x]][1];} bool ck(int x) {return x==ch[fa[x]][1];} void pushup(int x) { siz[x]=siz[ch[x][1]]+siz[ch[x][0]]+1; sum[x]=(sum[ch[x][0]]+sum[ch[x][1]]+val[x])%mod; } void pushdown(int x) { if(mul[x]!=1) { if(ch[x][1]) (sum[ch[x][1]]*=mul[x])%=mod, (val[ch[x][1]]*=mul[x])%=mod, (add[ch[x][1]]*=mul[x])%=mod, (mul[ch[x][1]]*=mul[x])%=mod; if(ch[x][0]) (sum[ch[x][0]]*=mul[x])%=mod, (val[ch[x][0]]*=mul[x])%=mod, (add[ch[x][0]]*=mul[x])%=mod, (mul[ch[x][0]]*=mul[x])%=mod; mul[x]=1; } if(add[x]) { if(ch[x][0]) (sum[ch[x][0]]+=add[x]*siz[ch[x][0]])%=mod, (val[ch[x][0]]+=add[x])%=mod, (add[ch[x][0]]+=add[x])%=mod; if(ch[x][1]) (sum[ch[x][1]]+=add[x]*siz[ch[x][1]])%=mod, (val[ch[x][1]]+=add[x])%=mod, (add[ch[x][1]]+=add[x])%=mod; add[x]=0; } if(rev[x]) { swap(ch[x][0],ch[x][1]); rev[ch[x][0]]^=1;rev[ch[x][1]]^=1; rev[x]=0; } } void rotate(int x) { int f=fa[x],ff=fa[f]; if(!is_rt(f)) ch[ff][ck(f)]=x; bool tag=ck(x); ch[f][tag]=ch[x][tag^1]; fa[ch[f][tag]]=f; ch[x][tag^1]=f; fa[f]=x; fa[x]=ff; pushup(f);pushup(x); } int stk[N],top; void splay(int x) { stk[top=1]=x; for(int i=x;!is_rt(i);i=fa[i]) stk[++top]=fa[i]; for(int i=top;i;i--) pushdown(stk[i]); for(int f;!is_rt(x);rotate(x)) { if(!is_rt(f=fa[x])) rotate(ck(f)==ck(x)?f:x); } } void access(int x) { for(int t=0;x;t=x,x=fa[x]) { splay(x);ch[x][1]=t;pushup(x); } } void makeroot(int x) { access(x); splay(x); rev[x]^=1; } void link(int x,int y) { makeroot(x); fa[x]=y; } void cut(int x,int y) { makeroot(x);access(y);splay(y); ch[y][0]=fa[x]=0; } int main() { scanf("%d%d",&n,&q); for(int i=1;i<N;i++) mul[i]=1,val[i]=1,siz[i]=1; for(int i=1,u,v;i<n;i++) scanf("%d%d",&u,&v),link(u,v); char opt[10];int a,b,c,d; while(q--) { scanf("%s",opt); switch(opt[0]) { case '+':scanf("%d%d%d",&a,&b,&c); makeroot(a);access(b);splay(b); (add[b]+=c)%=mod;(val[b]+=c)%=mod;(sum[b]+=c*siz[b])%=mod;break; case '-':scanf("%d%d%d%d",&a,&b,&c,&d);cut(a,b),link(c,d);break; case '*':scanf("%d%d%d",&a,&b,&c); makeroot(a),access(b);splay(b); (mul[b]*=c)%=mod;(val[b]*=c)%=mod;(sum[b]*=c)%=mod;(add[b]*=c)%=mod;break; case '/':scanf("%d%d",&a,&b); makeroot(a),access(b);splay(b); printf("%lld ",sum[b]);break; } } }