BZOJ 2631: tree LCT

来源:互联网 发布:java 图片裁剪工具类 编辑:程序博客网 时间:2024/05/16 07:29

2631: tree

Time Limit: 30 Sec  Memory Limit: 128 MB
Submit: 4855  Solved: 1659
[Submit][Status][Discuss]

Description

 一棵n个点的树,每个点的初始权值为1。对于这棵树有q个操作,每个操作为以下四种操作之一:
+ u v c:将u到v的路径上的点的权值都加上自然数c;
- u1 v1 u2 v2:将树中原有的边(u1,v1)删除,加入一条新边(u2,v2),保证操作完之后仍然是一棵树;
* u v c:将u到v的路径上的点的权值都乘上自然数c;
/ u v:询问u到v的路径上的点的权值和,求出答案对于51061的余数。

Input

  第一行两个整数n,q
接下来n-1行每行两个正整数u,v,描述这棵树
接下来q行,每行描述一个操作

Output

  对于每个/对应的答案输出一行

Sample Input

3 2
1 2
2 3
* 1 3 4
/ 1 1

Sample Output

4

HINT

数据规模和约定
10%的数据保证,1<=n,q<=2000
另外15%的数据保证,1<=n,q<=5*10^4,没有-操作,并且初始树为一条链
另外35%的数据保证,1<=n,q<=5*10^4,没有-操作
100%的数据保证,1<=n,q<=10^5,0<=c<=10^4


LCT练手题


pushdown写错调一上午。

#include<cmath>#include<ctime>#include<cstdio>#include<cstring>#include<cstdlib>#include<iostream>#include<algorithm>#include<iomanip>#include<vector>#include<string>#include<bitset>#include<queue>#include<set>#include<map>using namespace std;typedef unsigned int uint;inline int read(){int x=0,f=1;char ch=getchar();while(ch<'0'||ch>'9'){if(ch=='-')f=-1;ch=getchar();}while(ch<='9'&&ch>='0'){x=x*10+ch-'0';ch=getchar();}return x*f;}void print(int x){if(x<0)putchar('-'),x=-x;if(x>=10)print(x/10);putchar(x%10+'0');}const int N=100100,mod=51061;int ch[N][2],size[N],fa[N];uint V[N],sum[N],add[N],mul[N];bool rev[N];inline void pushup(int k){int ls=ch[k][0],rs=ch[k][1];size[k]=size[ls]+size[rs]+1;sum[k]=(sum[ls]+sum[rs]+V[k])%mod;}inline void pushdown(int k){int ls=ch[k][0],rs=ch[k][1];if(mul[k]!=1){(V[ls]*=mul[k])%=mod;(V[rs]*=mul[k])%=mod;(mul[ls]*=mul[k])%=mod;(mul[rs]*=mul[k])%=mod;(add[ls]*=mul[k])%=mod;(add[rs]*=mul[k])%=mod;(sum[ls]*=mul[k])%=mod;(sum[rs]*=mul[k])%=mod;mul[k]=1;}if(add[k]){sum[ls]=(sum[ls]+add[k]*size[ls])%mod;sum[rs]=(sum[rs]+add[k]*size[rs])%mod;(add[ls]+=add[k])%=mod;(add[rs]+=add[k])%=mod;(V[ls]+=add[k])%=mod;(V[rs]+=add[k])%=mod;add[k]=0;}if(rev[k]){rev[k]=0;rev[ls]^=1;rev[rs]^=1;swap(ch[k][0],ch[k][1]);}}inline bool isroot(int k){return ch[fa[k]][0]!=k&&ch[fa[k]][1]!=k;}void getdown(int k){if(!isroot(k)) getdown(fa[k]);pushdown(k);}inline void rotate(int x){int y=fa[x],z=fa[y],l,r;l=(ch[y][1]==x);r=l^1;if(!isroot(y)) ch[z][ch[z][1]==y]=x;fa[x]=z;fa[y]=x;fa[ch[x][r]]=y;ch[y][l]=ch[x][r];ch[x][r]=y;pushup(y);pushup(x);}void splay(int x){getdown(x);int y,z;while(!isroot(x)){y=fa[x];z=fa[y];if(!isroot(y)){if((ch[y][0]==x)^(ch[z][0]==y))rotate(x);else rotate(y);}rotate(x);}}void access(int x){int t=0;while(x){splay(x);ch[x][1]=t;pushup(x);t=x;x=fa[x];}}void rever(int x){access(x);splay(x);rev[x]^=1;}void split(int u,int v){rever(u);access(v);splay(v);}void link(int u,int v){rever(u);fa[u]=v;splay(u);}void cut(int u,int v){split(u,v);ch[v][0]=fa[u]=0;}void modify_add(int u,int v,int val){split(v,u);sum[u]=(sum[u]+size[u]*val)%mod;(add[u]+=val)%=mod;(V[u]+=val)%=mod;}void modify_mul(int u,int v,int val){split(v,u);(sum[u]*=val)%=mod;(mul[u]*=val)%=mod;(add[u]*=val)%=mod;(V[u]*=val)%=mod;}void query(int u,int v){split(v,u);print(sum[u]);puts("");}int main(){register int n=read(),Q=read();register int u,v,x,y;for(u=1;u<=n;++u)mul[u]=V[u]=sum[u]=size[u]=1;for(x=1;x<n;++x){u=read();v=read();link(u,v);}char opt[2];while(Q--){scanf("%s",opt);u=read();v=read();switch(opt[0]){case '+':x=read();modify_add(u,v,x);break;case '-':x=read();y=read();cut(u,v);link(x,y);break;case '*':x=read();modify_mul(u,v,x);break;case '/':query(u,v);break;}}return 0;}

原创粉丝点击