LUOGU P1501 [國家集訓隊]Tree II (lct)
阿新 • • 發佈:2018-11-21
解題思路
\(lct\),比較模板的一道題,路徑加和乘的維護標記與線段樹\(2\)差不多,然後剩下就沒啥了。但調了我將近一下午。。
程式碼
#include<iostream> #include<cstdio> #include<cstring> #include<cstdlib> #include<algorithm> #define int long long using namespace std; const int MAXN = 100005; const int MOD = 51061; inline int rd(){ int x=0,f=1;char ch=getchar(); while(!isdigit(ch)) {f=ch=='-'?0:1;ch=getchar();} while(isdigit(ch)) {x=(x<<1)+(x<<3)+ch-'0';ch=getchar();} return f?x:-x; } int n,q,fa[MAXN],sum[MAXN],ch[MAXN][2],w[MAXN]; int tag_mul[MAXN],tag_add[MAXN],siz[MAXN]; bool tag[MAXN]; inline void pushup(int x){ sum[x]=sum[ch[x][0]]+sum[ch[x][1]]+w[x];sum[x]%=MOD; siz[x]=siz[ch[x][0]]+siz[ch[x][1]]+1; } inline bool isroot(int x){ return (x!=ch[fa[x]][0] && x!=ch[fa[x]][1]); } inline bool check(int x){ return (x==ch[fa[x]][1]); } inline void pushdown(int x){ if(tag[x]){ if(ch[x][0]) tag[ch[x][0]]^=1,swap(ch[ch[x][0]][0],ch[ch[x][0]][1]); if(ch[x][1]) tag[ch[x][1]]^=1,swap(ch[ch[x][1]][0],ch[ch[x][1]][1]); tag[x]=0; } if(tag_mul[x]!=-1){ if(ch[x][0]){ if(tag_add[ch[x][0]]!=-1) (tag_add[ch[x][0]]*=tag_mul[x])%=MOD; if(tag_mul[ch[x][0]]==-1) tag_mul[ch[x][0]]=tag_mul[x]; else (tag_mul[ch[x][0]]*=tag_mul[x])%=MOD; w[ch[x][0]]*=tag_mul[x];w[ch[x][0]]%=MOD; sum[ch[x][0]]*=tag_mul[x];sum[ch[x][0]]%=MOD; } if(ch[x][1]){ if(tag_add[ch[x][1]]!=-1) (tag_add[ch[x][1]]*=tag_mul[x])%=MOD; if(tag_mul[ch[x][1]]==-1) tag_mul[ch[x][1]]=tag_mul[x]; else (tag_mul[ch[x][1]]*=tag_mul[x])%=MOD; w[ch[x][1]]*=tag_mul[x];w[ch[x][1]]%=MOD; sum[ch[x][1]]*=tag_mul[x];sum[ch[x][1]]%=MOD; } tag_mul[x]=-1; } if(tag_add[x]!=-1) { if(ch[x][0]) { if(tag_add[ch[x][0]]==-1) tag_add[ch[x][0]]=tag_add[x]; else (tag_add[ch[x][0]]+=tag_add[x])%=MOD; (w[ch[x][0]]+=tag_add[x])%=MOD; sum[ch[x][0]]+=siz[ch[x][0]]*tag_add[x];sum[ch[x][0]]%=MOD; } if(ch[x][1]){ if(tag_add[ch[x][1]]==-1) tag_add[ch[x][1]]=tag_add[x]; else (tag_add[ch[x][1]]+=tag_add[x])%=MOD; (w[ch[x][1]]+=tag_add[x])%=MOD; sum[ch[x][1]]+=siz[ch[x][1]]*tag_add[x];sum[ch[x][1]]%=MOD; } tag_add[x]=-1; } } inline void update(int x){ if(!isroot(x)) update(fa[x]);pushdown(x); } inline void rotate(int x){ int y=fa[x],z=fa[y];bool chk=check(x); if(!isroot(y)) ch[z][y==ch[z][1]]=x; ch[y][chk]=ch[x][chk^1];fa[ch[x][chk^1]]=y; fa[y]=x;ch[x][chk^1]=y;fa[x]=z; pushup(y);pushup(x); } inline void splay(int x){ update(x); for(;!isroot(x);rotate(x)) if(!isroot(fa[x])) rotate(check(fa[x])==check(x)?fa[x]:x); } inline void access(int x){ for(int y=0;x;y=x,x=fa[x]) splay(x),ch[x][1]=y,pushup(x); } inline int findroot(int x){ access(x);splay(x); while(ch[x][0]) pushdown(x),x=ch[x][0]; return x; } inline void makeroot(int x){ access(x);splay(x); tag[x]^=1;swap(ch[x][0],ch[x][1]); } 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);fa[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]) fa[x]=0,ch[y][0]=0,pushup(y); } inline void update_add(int x,int y,int k){ split(x,y);sum[x]+=siz[x]*k;sum[x]%=MOD; if(tag_add[y]!=-1) (tag_add[y]+=k)%=MOD ;else tag_add[y]=k; w[y]+=k;pushup(y);w[y]%=MOD; } inline void update_mul(int x,int y,int k){ split(x,y);sum[x]*=k;sum[x]%=MOD; if(tag_add[y]!=-1) (tag_add[y]*=k)%=MOD; if(tag_mul[y]!=-1) (tag_mul[y]*=k)%=MOD;else tag_mul[y]=k; w[y]*=k;pushup(y);w[y]%=MOD; } signed main(){ memset(tag_mul,-1,sizeof(tag_mul)); memset(tag_add,-1,sizeof(tag_add)); int x,y,a,b;char c;n=rd(),q=rd(); for(int i=1;i<=n;i++) w[i]=1; for(int i=1;i<n;i++){ x=rd(),y=rd(); link(x,y); } while(q--){ scanf("%c",&c); if(c=='+'){ x=rd(),y=rd(),a=rd(); update_add(x,y,a); } else if(c=='-'){ x=rd(),y=rd(),a=rd(),b=rd(); cut(x,y);link(a,b); } else if(c=='*') { x=rd(),y=rd(),a=rd(); update_mul(x,y,a); } else { x=rd(),y=rd(); split(x,y);printf("%lld\n",sum[y]); } } return 0; }