2631: tree
Time Limit: 30 Sec Memory Limit: 128 MBDescription
一棵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行,每行描述一个操作
接下来n-1行每行两个正整数u,v,描述这棵树
接下来q行,每行描述一个操作
Output
对于每个/对应的答案输出一行
Sample Input
3 2
1 2
2 3
* 1 3 4
/ 1 1
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
Source
LCT入门题,,
md一个%=写成了%改了我一天。。。
#include<map> #include<cmath> #include<queue> #include<cstdio> #include<cstring> #include<iostream> #include<algorithm> using namespace std; #define inf 1000000007 #define ll long long #define uint unsigned int #define mod 51061 #define N 100010 inline int rd() { int x=0;char ch=getchar(); while(ch<'0'||ch>'9') ch=getchar(); while(ch>='0'&&ch<='9'){x=x*10+ch-'0';ch=getchar();} return x; } int c[N][2],fa[N],sz[N]; uint lz1[N],lz2[N],v[N],sum[N]; bool rev[N]; int n,q; #define ls c[x][0] #define rs c[x][1] bool isrt(int x){return x!=c[fa[x]][0]&&x!=c[fa[x]][1];} inline void pd(int x) { uint mz; if(rev[x]) { rev[ls]^=1;rev[rs]^=1; swap(ls,rs);rev[x]=0; } mz=lz2[x];lz2[x]=1; if(mz!=1) { lz2[ls]=lz2[ls]*mz%mod; lz2[rs]=lz2[rs]*mz%mod; lz1[ls]=lz1[ls]*mz%mod; lz1[rs]=lz1[rs]*mz%mod; sum[ls]=sum[ls]*mz%mod; sum[rs]=sum[rs]*mz%mod; v[ls]=v[ls]*mz%mod;v[rs]=v[rs]*mz%mod; } mz=lz1[x];lz1[x]=0; if(mz) { (lz1[ls]+=mz)%=mod; (lz1[rs]+=mz)%=mod; (sum[ls]+=sz[ls]*mz)%=mod; (sum[rs]+=sz[rs]*mz)%=mod; (v[ls]+=mz)%=mod;(v[rs]+=mz)%=mod; } } inline void upd(int x) { sz[x]=sz[ls]+sz[rs]+1; sum[x]=(v[x]+sum[ls]+sum[rs])%mod; } void rot(int x) { int y=fa[x],z=fa[y],l,r; l=c[y][1]==x;r=l^1; if(!isrt(y)) c[z][c[z][1]==y]=x; fa[x]=z;fa[y]=x;fa[c[x][r]]=y; c[y][l]=c[x][r];c[x][r]=y; upd(y);upd(x); } int st[N],tot; void splay(int x) { tot=1;st[1]=x; for(int i=x;!isrt(i);i=fa[i]) st[++tot]=fa[i]; for(int i=tot;i;i--) pd(st[i]); int y,z; while(!isrt(x)) { y=fa[x];z=fa[y]; if(!isrt(y)) { if((c[y][0]==x)^(c[z][0]==y)) rot(x); else rot(y); } rot(x); } } void acc(int x) { int t=0; while(x) { splay(x); rs=t;upd(x); t=x;x=fa[x]; } } void rever(int x) { acc(x); splay(x); rev[x]^=1; } void mk(int x,int y) { rever(x); acc(y);splay(y); } void link(int x,int y) { rever(x); fa[x]=y; } void cut(int x,int y) { mk(x,y); c[y][0]=fa[x]=0; } inline void mul(int x,int V) { (v[x]*=V)%=mod; (sum[x]*=V)%=mod; (lz2[x]*=V)%=mod; (lz1[x]*=V)%=mod; } inline void add(int x,int V) { (v[x]+=V)%=mod; (sum[x]+=V*sz[x])%=mod; (lz1[x]+=V)%=mod; } int main() { n=rd();q=rd(); for(int i=1;i<=n;i++) lz2[i]=sz[i]=sum[i]=v[i]=1; for(int i=1,x,y;i<n;i++) { x=rd();y=rd(); link(x,y); } char op[2]; int x,y,xx,yy,V; while(q--) { scanf("%s",op); if(op[0]=='*') { x=rd();y=rd();V=rd(); mk(x,y);mul(y,V); } else if(op[0]=='+') { x=rd();y=rd();V=rd(); mk(x,y);add(y,V); } else if(op[0]=='-') { x=rd();y=rd();xx=rd();yy=rd(); cut(x,y);link(xx,yy); } else { x=rd();y=rd(); mk(x,y);printf("%d ",sum[y]); } } return 0; }