Description:
一棵
n
个点的树,每个点的初始权值为
∗ u v c:
将
u
到
Solution:
LCT
直接上,
Splay
维护每一条链的和,然后记录一个
add,mult
来作为标记。
Code:
#include <cstdio>
#include <cstdlib>
#include <cstring>
#include <cmath>
#include <algorithm>
#include <iostream>
using namespace std;
int N,Q;
const long long Mod=51061;
struct tree_
{
int fa1;
int fa2;
int son[2];
long long sum;
long long add;
long long mult;
int rev;
long long Size;
}tree[100010]={{0,0,{0},0,0,0,0,0}};
struct bian_
{
int to;
int next;
}bian[200010]={{0,0}};
int First[100010]={0};
void Add(int p,int q,int k)
{
bian[k].to=q;
bian[k].next=First[p];
First[p]=k;
return;
}
void dfs(int cnt,int fa)
{
tree[cnt].sum=tree[cnt].Size=1;
for(int i=First[cnt];i!=0;i=bian[i].next)
{
if(bian[i].to==fa) continue;
tree[bian[i].to].fa2=cnt;
dfs(bian[i].to,cnt);
}
return;
}
void rotate(int k)
{
int Fa=tree[k].fa1;
if(tree[Fa].fa1==0)
swap(tree[Fa].fa2,tree[k].fa2);
int g=(tree[Fa].son[1]==k);
swap(tree[k].Size,tree[Fa].Size);
tree[Fa].Size+=tree[tree[Fa].son[g^1]].Size-tree[tree[k].son[g]].Size;
int SS=tree[Fa].sum;
tree[Fa].sum-=tree[k].sum-tree[tree[k].son[g^1]].sum;
tree[Fa].sum=(tree[Fa].sum+Mod)%Mod;
tree[k].sum=SS;
tree[Fa].son[g]=tree[k].son[g^1];
if(tree[k].son[g^1]!=0)
tree[tree[k].son[g^1]].fa1=Fa;
tree[k].son[g^1]=Fa;
tree[k].fa1=tree[Fa].fa1;
if(tree[Fa].fa1!=0)
{
int gg=(tree[tree[Fa].fa1].son[1]==Fa);
tree[tree[Fa].fa1].son[gg]=k;
}
tree[Fa].fa1=k;
return;
}
void update(int k)
{
if(tree[k].fa1!=0)
update(tree[k].fa1);
for(int i=0;i<=1;i++)
{
if(tree[k].son[i]!=0)
{
int child=tree[k].son[i];
tree[child].rev^=tree[k].rev;
tree[child].sum=(tree[child].sum*(tree[k].mult+1)+tree[k].add*tree[child].Size)%Mod;
tree[child].add=(tree[child].add*(tree[k].mult+1)+tree[k].add)%Mod;
tree[child].mult=((tree[child].mult+1)*(tree[k].mult+1)-1)%Mod;
if(tree[k].rev&1)
swap(tree[child].son[0],tree[child].son[1]);
}
}
tree[k].rev=tree[k].add=tree[k].mult=0;
return;
}
void Splay(int k)
{
update(k);
for(;tree[k].fa1!=0;)
{
int Fa=tree[k].fa1;
if(tree[Fa].fa1==0)
rotate(k);
else
{
int g1=(tree[Fa].son[1]==k),g2=(tree[tree[Fa].fa1].son[1]==Fa);
if(g1==g2)
rotate(Fa),rotate(k);
else rotate(k),rotate(k);
}
}
return;
}
void cut(int k,int g)
{
int child=tree[k].son[g];
swap(tree[child].fa1,tree[child].fa2);
tree[k].sum=(tree[k].sum-tree[child].sum+Mod)%Mod;
tree[k].Size-=tree[child].Size;
tree[k].son[g]=0;
return;
}
void access(int k)
{
Splay(k);
if(tree[k].son[1]!=0)
cut(k,1);
for(;;)
{
if(tree[k].fa2==0)
break;
int O=tree[k].fa2;
Splay(O);
if(tree[O].son[1]!=0)
cut(O,1);
tree[O].Size+=tree[k].Size;
tree[O].sum=(tree[O].sum+tree[k].sum)%Mod;
tree[O].son[1]=k;
swap(tree[k].fa1,tree[k].fa2);
Splay(k);
}
return;
}
int main()
{
scanf("%d%d",&N,&Q);
for(int i=1;i<N;i++)
{
int p,q;
scanf("%d%d",&p,&q);
Add(p,q,(i<<1)-1);
Add(q,p,i<<1);
}
dfs(1,0);
for(int i=1;i<=Q;i++)
{
char ch='\0';
for(ch=getchar();!(ch=='-' || ch=='+' || ch=='*' || ch=='/');ch=getchar());
if(ch=='+')
{
int u,v,r;
scanf("%d%d%d",&u,&v,&r);
long long increase=(long long)r%Mod;
access(u);
tree[u].rev^=1;
swap(tree[u].son[0],tree[u].son[1]);
access(v);
update(v);
tree[v].sum=(tree[v].sum+increase*tree[v].Size)%Mod;
tree[v].add=increase;
}
if(ch=='-')
{
int u,v,p,q;
scanf("%d%d%d%d",&u,&v,&p,&q);
access(u);
tree[u].rev^=1;
swap(tree[u].son[0],tree[u].son[1]);
access(v);
tree[v].sum=(tree[v].sum-tree[u].sum+Mod)%Mod;
tree[v].Size-=tree[u].Size;
tree[u].fa1=tree[v].son[0]=0;
access(q);
tree[q].rev^=1;
swap(tree[q].son[0],tree[q].son[1]);
tree[q].fa2=p;
}
if(ch=='*')
{
int u,v,r;
scanf("%d%d%d",&u,&v,&r);
long long cheng=(long long)r%Mod;
access(u);
tree[u].rev^=1;
swap(tree[u].son[0],tree[u].son[1]);
access(v);
update(v);
tree[v].sum=tree[v].sum*cheng%Mod;
tree[v].mult=cheng-1;
}
if(ch=='/')
{
int u,v;
scanf("%d%d",&u,&v);
access(u);
tree[u].rev^=1;
swap(tree[u].son[0],tree[u].son[1]);
access(v);
printf("%d\n",(int)tree[v].sum);
}
}
return 0;
}