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行,每行描述一个操作
接下来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
用LCT维护即可
注意加法和乘法标记合并时候的顺序
用long long存储结果结果TLE了
发现Mod^2<unsigned int
所以用unsigned int存就可以过了
#include<cstdio>
#include<string>
#include<cstring>
#include<iostream>
#include<algorithm>
using namespace std;
int n;
unsigned int mod=51061;
struct line
{
int s,t;
}a[100001];
struct tree
{
int l,r;
int fa;
int rev;
unsigned int sz,val,tag,tagx;
bool rt;
}tr[800001];
unsigned int val[200001];
tree nx;
inline void update_rev(int x)
{
if(x==0)
return ;
int t=tr[x].l;
tr[x].l=tr[x].r;
tr[x].r=t;
tr[x].rev^=1;
}
inline void push_up(int x)
{
tr[x].sz=(tr[tr[x].l].sz+tr[tr[x].r].sz+1)%mod;
tr[x].val=(tr[tr[x].l].val+tr[tr[x].r].val+val[x])%mod;
}
inline void push_down(int x)
{
if(tr[x].rev)
{
update_rev(tr[x].l);
update_rev(tr[x].r);
tr[x].rev=0;
}
val[tr[x].l]=(val[tr[x].l]*tr[x].tagx)%mod;
val[tr[x].r]=(val[tr[x].r]*tr[x].tagx)%mod;
tr[tr[x].l].val=tr[tr[x].l].val*tr[x].tagx%mod;
tr[tr[x].r].val=tr[tr[x].r].val*tr[x].tagx%mod;
tr[tr[x].l].tag=(tr[tr[x].l].tag*tr[x].tagx)%mod;
tr[tr[x].r].tag=(tr[tr[x].r].tag*tr[x].tagx)%mod;
tr[tr[x].l].tagx=(tr[tr[x].l].tagx*tr[x].tagx)%mod;
tr[tr[x].r].tagx=(tr[tr[x].r].tagx*tr[x].tagx)%mod;
tr[x].tagx=1;
val[tr[x].l]=(val[tr[x].l]+tr[x].tag)%mod;
val[tr[x].r]=(val[tr[x].r]+tr[x].tag)%mod;
tr[tr[x].l].val=(tr[tr[x].l].val+tr[x].tag*tr[tr[x].l].sz%mod)%mod;
tr[tr[x].r].val=(tr[tr[x].r].val+tr[x].tag*tr[tr[x].r].sz%mod)%mod;
tr[tr[x].l].tag=(tr[tr[x].l].tag+tr[x].tag)%mod;
tr[tr[x].r].tag=(tr[tr[x].r].tag+tr[x].tag)%mod;
tr[x].tag=0;
}
inline void push(int x)
{
if(!tr[x].rt)
push(tr[x].fa);
push_down(x);
}
inline void zig(int x)
{
tr[0]=nx;
int t=tr[x].l;
tr[x].l=tr[t].r;
tr[tr[t].r].fa=x;
tr[t].r=x;
tr[t].fa=tr[x].fa;
tr[x].fa=t;
if(tr[x].rt)
{
tr[x].rt=false;
tr[t].rt=true;
}
else
{
if(x==tr[tr[t].fa].l)
tr[tr[t].fa].l=t;
else
tr[tr[t].fa].r=t;
}
push_up(x);
}
inline void zag(int x)
{
tr[0]=nx;
int t=tr[x].r;
tr[x].r=tr[t].l;
tr[tr[t].l].fa=x;
tr[t].l=x;
tr[t].fa=tr[x].fa;
tr[x].fa=t;
if(tr[x].rt)
{
tr[x].rt=false;
tr[t].rt=true;
}
else
{
if(x==tr[tr[t].fa].l)
tr[tr[t].fa].l=t;
else
tr[tr[t].fa].r=t;
}
push_up(x);
}
inline void splay(int x)
{
push(x);
while(!tr[x].rt)
{
int y=tr[x].fa,z=tr[y].fa;
if(tr[y].rt)
{
if(x==tr[y].l)
zig(y);
else
zag(y);
}
else if(y==tr[z].l)
{
if(x==tr[y].l){zig(z);zig(y);}
else{zag(y);zig(z);}
}
else
{
if(x==tr[y].r){zag(z);zag(y);}
else{zig(y);zag(z);}
}
}
push_up(x);
}
inline void access(int x)
{
int y=0;
while(x!=0)
{
splay(x);
tr[tr[x].r].rt=true;
tr[x].r=y;
tr[y].rt=false;
push_up(x);
y=x;
x=tr[x].fa;
}
}
inline int findroot(int x)
{
access(x);
splay(x);
while(tr[x].l!=0)
x=tr[x].l;
return x;
}
inline bool judge(int s,int t)
{
s=findroot(s);
t=findroot(t);
if(s==t)
return true;
return false;
}
inline void mroot(int x)
{
// push_up(x);
access(x);
splay(x);
update_rev(x);
}
inline void link(int s,int t)
{
if(judge(s,t))
return ;
mroot(s);
tr[s].fa=t;
//access(s);
}
inline void cut(int s,int t)
{
if(s==t||!judge(s,t))
return ;
mroot(s);
access(t);
splay(t);
tr[tr[t].l].fa=0;
tr[tr[t].l].rt=true;
tr[t].l=0;
push_up(t);
}
inline int ask(int x,int y)
{
mroot(x);
access(y);
splay(y);
return (tr[tr[y].l].val+val[y])%mod;
}
inline int add1(int x,int y,unsigned int xx)
{
mroot(x);
access(y);
splay(y);
val[y]=(val[y]+xx)%mod;
val[tr[y].l]=(val[tr[y].l]+xx)%mod;
tr[tr[y].l].val=(tr[tr[y].l].val+tr[tr[y].l].sz*xx%mod)%mod;
tr[tr[y].l].tag=(tr[tr[y].l].tag+xx)%mod;
push_up(y);
/*tr[tr[y].l].tag=(tr[tr[y].l].tag+xx)%mod;
tr[tr[y].r].tag=(tr[tr[y].r].tag+xx)%mod;*/
}
inline int add2(int x,int y,unsigned int xx)
{
mroot(x);
access(y);
splay(y);
val[y]=(val[y]*xx)%mod;
val[tr[y].l]=(val[tr[y].l]*xx)%mod;
tr[tr[y].l].val=tr[tr[y].l].val*xx%mod;
tr[tr[y].l].tag=(tr[tr[y].l].tag*xx)%mod;
tr[tr[y].l].tagx=(tr[tr[y].l].tagx*xx)%mod;
push_up(y);
/* tr[tr[y].l].tagx=(tr[tr[y].l].tagx*xx)%mod;
tr[tr[y].r].tagx=(tr[tr[y].r].tagx*xx)%mod;*/
}
int main()
{
// freopen("data.in","r",stdin);
// freopen("data.out","w",stdout);
int m;
scanf("%d%d",&n,&m);
int i;
int s,t,x;
for(i=1;i<=n-1;i++)
scanf("%d%d",&a[i].s,&a[i].t);
for(i=1;i<=n;i++)
{
val[i]=1;
tr[i].val=val[i];
tr[i].sz=1;
tr[i].rt=true;
tr[i].tagx=1;
}
for(i=1;i<=n-1;i++)
link(a[i].s,a[i].t);
char xx[11];
int s1,t1;
for(i=1;i<=m;i++)
{
scanf("%s",xx);
if(xx[0]=='+')
{
scanf("%d%d%d",&s,&t,&s1);
add1(s,t,s1);
}
else if(xx[0]=='-')
{
scanf("%d%d%d%d",&s,&t,&s1,&t1);
cut(s,t);
link(s1,t1);
}
else if(xx[0]=='*')
{
scanf("%d%d%d",&s,&t,&s1);
add2(s,t,s1);
}
else
{
scanf("%d%d",&s,&t);
printf("%u\n",ask(s,t));
}
}
return 0;
}