bzoj2631: tree
话说bzoj上叫tree的题可真多...
题目大意:路径加,路径乘,路径求和,加边删边。
思路:动态树搞搞就行了,两个标记要注意。
#include<cstdio> #include<cstring> #include<algorithm> #define ll unsigned int #define ls c[x][0] #define rs c[x][1] const int mod=51061,maxn=100010; using namespace std; int n,m;char op[2]; struct LCT{ int fa[maxn],c[maxn][2],size[maxn],rev[maxn]; ll sum[maxn],val[maxn],mul[maxn],add[maxn]; bool isroot(int x){return c[fa[x]][0]!=x&&c[fa[x]][1]!=x;} int which(int x){return c[fa[x]][1]==x;} void update(int x){ // printf("update%d %d %d\n",x,sum[x],size[x]); sum[x]=(sum[ls]+sum[rs]+val[x])%mod; size[x]=(size[ls]+size[rs]+1)%mod; } void cal(int x,int m,int a){ if (!x) return ; val[x]=(val[x]*m+a)%mod; sum[x]=(sum[x]*m+a*size[x])%mod; add[x]=(add[x]*m+a)%mod; mul[x]=(mul[x]*m)%mod; // printf("%d %d %d %d\n",x,sum[x],mul[x],add[x]); } void flip(int x){swap(c[x][0],c[x][1]),rev[x]^=1;} void down(int x){ if (rev[x]) flip(c[x][0]),flip(c[x][1]),rev[x]^=1; if (mul[x]!=1||add[x]) cal(ls,mul[x],add[x]),cal(rs,mul[x],add[x]),mul[x]=1,add[x]=0; } void relax(int x){if (!isroot(x)) relax(fa[x]);down(x);} void rotate(int x){ int y=fa[x],z=fa[y],nx=which(x),ny=which(y); // printf("%d %d %d %d\n",x,sum[x],mul[x],add[x]); fa[c[x][!nx]]=y,c[y][nx]=c[x][!nx]; fa[x]=z;if (!isroot(y)) c[z][ny]=x; fa[y]=x,c[x][!nx]=y;update(y); } void splay(int x){ relax(x); while (!isroot(x)){ if (isroot(fa[x])) rotate(x); else if (which(x)==which(fa[x])) rotate(fa[x]),rotate(x); else rotate(x),rotate(x); } update(x); } void access(int x){for (int p=0;x;x=fa[x]) splay(x),fa[c[x][1]=p]=x,update(x),p=x;} void makeroot(int x){access(x),splay(x),flip(x);} void link(int a,int b){makeroot(a),fa[a]=b;} void cut(int a,int b){makeroot(a),access(b),splay(b),c[b][0]=fa[a]=0;} void change(int a1,int b1,int a2,int b2){cut(a1,b1),link(a2,b2);} void qsum(int a,int b){makeroot(a),access(b),splay(b),printf("%d\n",sum[b]);} void modify(int a,int b,int m,int ad){makeroot(a),access(b),splay(b),cal(b,m,ad);} }T; int main(){ scanf("%d%d",&n,&m); for (int i=1;i<=n;i++) T.size[i]=T.val[i]=T.sum[i]=T.mul[i]=1; for (int i=1,a,b;i<n;i++) scanf("%d%d",&a,&b),T.link(a,b); for (int i=1,a,b,c,d;i<=m;i++){ scanf("%s",op); if (op[0]=='+') scanf("%d%d%d",&a,&b,&c),T.modify(a,b,1,c); else if (op[0]=='-') scanf("%d%d%d%d",&a,&b,&c,&d),T.change(a,b,c,d); else if (op[0]=='*') scanf("%d%d%d",&a,&b,&c),T.modify(a,b,c,0); else scanf("%d%d",&a,&b),T.qsum(a,b); } return 0; }