Luogu1501 [國家集訓隊]Tree II
阿新 • • 發佈:2020-08-10
https://www.luogu.com.cn/problem/P1501
\(LCT\)
注意標記的下放,需要記住一個原則
當該節點被打上標記時,該節點的值需要同時更新
下放標記時直接傳給兒子,這時已經不能更新自己了
採取邊更新邊下放的方式到處都是鍋
#include<cstdio> #include<algorithm> #include<iostream> #define N 100005 #define ls(x) a[x].ch[0] #define rs(x) a[x].ch[1] #define fa(x) a[x].f #define v(x) a[x].val #define s(x) a[x].sz #define ans(x) a[x].Sum #define tag1(x) a[x].tag_add #define tag2(x) a[x].tag_muti #define tag(x) a[x].tag_reverse #define id(x) (ls(fa(x))==x?0:1) #define ll long long using namespace std; char cc; int x,y,x2,y2,n,m,q[N]; ll c; ll p=51061; struct node { int ch[2],f,tag_reverse; ll sz,val,Sum,tag_add,tag_muti; }a[N]; void update(int x) { s(x)=s(ls(x))+s(rs(x))+1; ans(x)=(ans(ls(x))+ans(rs(x))+v(x))%p; } void push_add(int x,ll y) { v(x)=(v(x)+y)%p; ans(x)=(ans(x)+s(x)*y)%p; tag1(x)=(tag1(x)+y)%p; } void push_mul(int x,ll y) { v(x)=v(x)*y%p; ans(x)=ans(x)*y%p; tag1(x)=tag1(x)*y%p; tag2(x)=tag2(x)*y%p; } void push_rev(int x) { tag(x)^=1; swap(ls(x),rs(x)); } void pushdown(int x) { if (tag(x)) { if (ls(x)) push_rev(ls(x)); if (rs(x)) push_rev(rs(x)); tag(x)=0; } if (tag2(x)!=1) { if (ls(x)) push_mul(ls(x),tag2(x)); if (rs(x)) push_mul(rs(x),tag2(x)); tag2(x)=1; } if (tag1(x)) { if (ls(x)) push_add(ls(x),tag1(x)); if (rs(x)) push_add(rs(x),tag1(x)); tag1(x)=0; } } bool isrt(int x) { return ls(fa(x))!=x && rs(fa(x))!=x; } void connect(int x,int F,int son) { fa(x)=F; a[F].ch[son]=x; } void rot(int x) { int y=fa(x),r=fa(y); int yson=id(x),rson=id(y); if (isrt(y)) fa(x)=r; else connect(x,r,rson); connect(a[x].ch[yson^1],y,yson); connect(y,x,yson^1); update(y),update(x); } void splay(int x) { int g=x,k=0; q[++k]=g; while (!isrt(g)) g=fa(g),q[++k]=g; while (k) pushdown(q[k--]); while (!isrt(x)) { int y=fa(x); if (isrt(y)) rot(x); else if (id(x)==id(y)) rot(y),rot(x); else rot(x),rot(x); } } void access(int x) { for (int y=0;x;y=x,x=fa(x)) splay(x),rs(x)=y,update(x); } void makeroot(int x) { access(x); splay(x); push_rev(x); } void split(int x,int y) { makeroot(x); access(y); splay(y); } void link(int x,int y) { makeroot(x); access(y); splay(y); fa(x)=y; } void cut(int x,int y) { makeroot(x); access(y); splay(y); fa(x)=ls(y)=0; update(y); } int main() { scanf("%d%d",&n,&m); for (int i=1;i<=n;i++) v(i)=ans(i)=1,s(i)=1,tag1(i)=0,tag2(i)=1; for (int i=1;i<n;i++) { scanf("%d%d",&x,&y); link(x,y); } for (int i=1;i<=m;i++) { cc=getchar(); while (cc!='+' && cc!='-' && cc!='*' && cc!='/') cc=getchar(); if (cc=='+') { scanf("%d%d%lld",&x,&y,&c); split(x,y); push_add(y,c); } else if (cc=='-') { scanf("%d%d%d%d",&x,&y,&x2,&y2); cut(x,y); link(x2,y2); } else if (cc=='*') { scanf("%d%d%lld",&x,&y,&c); split(x,y); push_mul(y,c); } else { scanf("%d%d",&x,&y); split(x,y); printf("%lld\n",ans(y)); } } return 0; }