BZOJ2631: tree link-cut-tree

来源:互联网 发布:异步加载js的方法 编辑:程序博客网 时间:2024/05/01 03:13

%lyh 一A 我脑残。。拍了半天 发现昨天脑子迷糊转错了。。

#include<iostream>#include<cstdio>#include<algorithm>#include<cstring>#define LL unsigned intusing namespace std;const int N=110000,P=51061;int tr[N][2],fa[N],n,m,size[N],q[N],top,rev[N];LL sum[N],val[N],lz1[N],lz2[N];bool isroot(int x){return tr[fa[x]][0]!=x&&tr[fa[x]][1]!=x;}void update(int x){int ls=tr[x][0],rs=tr[x][1];sum[x]=(sum[ls]+sum[rs]+val[x])%P;size[x]=(size[ls]+size[rs]+1)%P;}void Rev(int x){if(!x) return;swap(tr[x][0],tr[x][1]);rev[x]^=1;}void zig(int x){int y=fa[x];tr[y][0]=tr[x][1];if(tr[x][1]) fa[tr[x][1]]=y;tr[x][1]=y;fa[x]=fa[y];fa[y]=x;if(tr[fa[x]][0]==y) tr[fa[x]][0]=x; if(tr[fa[x]][1]==y) tr[fa[x]][1]=x;update(y);}void zag(int x){int y=fa[x];tr[y][1]=tr[x][0];if(tr[x][0]) fa[tr[x][0]]=y;tr[x][0]=y;fa[x]=fa[y];fa[y]=x;if(tr[fa[x]][0]==y) tr[fa[x]][0]=x;if(tr[fa[x]][1]==y) tr[fa[x]][1]=x;update(y);}void calc(int x,int m,int a){if(!x) return;val[x]=(val[x]*m+a)%P;sum[x]=(sum[x]*m+a*size[x])%P;lz1[x]=(lz1[x]*m+a)%P;lz2[x]=(lz2[x]*m)%P;}void down(int x){int ls=tr[x][0],rs=tr[x][1];if(rev[x]) {Rev(ls),Rev(rs);rev[x]=0;}int a=lz1[x],m=lz2[x];lz1[x]=0,lz2[x]=1;if(a!=0||m!=1){calc(ls,m,a);calc(rs,m,a);}}void splay(int x){int p=x;for(;!isroot(p);p=fa[p]) q[++top]=p;q[++top]=p;while(top) {down(q[top--]);}while(!isroot(x)){int y=fa[x];if(isroot(y)) {if(tr[y][0]==x) zig(x);else zag(x);}else {if(tr[fa[y]][0]==y){if(tr[y][0]==x) zig(y),zig(x);else zag(x),zig(x);}else {if(tr[y][1]==x) zag(y),zag(x);else zig(x),zag(x);}}}update(x);}void access(int x){for(int t=0;x;t=x,x=fa[x]) {splay(x);tr[x][1]=t;update(x);}}void makeroot(int x){access(x);splay(x);Rev(x);}void link(int y,int x){makeroot(x);fa[x]=y;}void split(int x,int y){//cout<<x<<" "<<y<<endl;makeroot(x);access(y);splay(y);}void cut(int x,int y){makeroot(x);access(y);splay(y);tr[y][0]=fa[x]=0;update(y);}int main(){scanf("%d%d",&n,&m);int u1,v1,u2,v2;for(int i=1;i<=n;i++) val[i]=sum[i]=size[i]=lz2[i]=1;for(int i=1;i<n;i++){scanf("%d%d",&u1,&v1);link(u1,v1);}char s[5];int k=0;while(m--){k++;scanf("%s",s+1);if(s[1]=='+'){scanf("%d%d%d",&u1,&v1,&u2);split(u1,v1);calc(v1,1,u2);}if(s[1]=='-'){scanf("%d%d%d%d",&u1,&v1,&u2,&v2);cut(u1,v1);link(u2,v2);}if(s[1]=='*'){scanf("%d%d%d",&u1,&v1,&u2);split(u1,v1);calc(v1,u2,0);}if(s[1]=='/'){scanf("%d%d",&u1,&v1);split(u1,v1);printf("%d\n",sum[v1]);}}return 0;}


0 0
原创粉丝点击