题目:
题解:
也算是LCT的模板题啦,只是这个乘和加的操作先后顺序要搞好
//记得很久以前做过一个线段树的维护乘和加
首先在传递的时候要把要传递下去的+乘上×(相当于这一层的+已经×好了)
那么遇到乘和加在同一级我们选择先×再+
这样的话传下去的时候就是deltac×然后deltaj+(传到下面的时候×就是×,+的话就是先×再把上一层的+加上)
说起来好方啊,大家还是自行参悟代码。。
震惊,3个字符的差异竟带来10s的代码快慢差异,真相竟是!
是。。。。把long long改成unsigned int。。。
代码:
#include <cstdio>
#include <iostream>
#define LL unsigned int
using namespace std;
const int N=100005;
const int Mod=51061;
int ch[N][2],f[N],deltaz[N],size[N],stack[N];
LL key[N],delta[N],sum[N],deltac[N];
int get(int x){return ch[f[x]][1]==x;}
void updata(int x)
{
sum[x]=(key[x]+(sum[ch[x][0]]+sum[ch[x][1]])%Mod)%Mod;
size[x]=size[ch[x][0]]+size[ch[x][1]]+1;
}
void mark(int x,int y,int z)
{
key[x]=(key[x]*z%Mod+y)%Mod;
sum[x]=(sum[x]*z%Mod+y*size[x]%Mod)%Mod;
deltac[x]=deltac[x]*z%Mod;
delta[x]=(delta[x]*z%Mod+y)%Mod;
}
void pushdown(int x)
{
if (deltaz[x])
{
swap(ch[x][0],ch[x][1]);
deltaz[ch[x][0]]^=1; deltaz[ch[x][1]]^=1;
deltaz[x]=0;
}
mark(ch[x][0],delta[x],deltac[x]);
mark(ch[x][1],delta[x],deltac[x]);
deltac[x]=1; delta[x]=0;
}
bool Is_root(int x){return ch[f[x]][0]!=x && ch[f[x]][1]!=x;}
void rotate(int x)
{
int old=f[x],oldf=f[old],which=get(x);bool gen=Is_root(old);
ch[old][which]=ch[x][which^1]; f[ch[x][which^1]]=old;
f[old]=x; ch[x][which^1]=old;
f[x]=oldf; if (!gen) ch[oldf][ch[oldf][1]==old]=x;
updata(old);
updata(x);
}
void splay(int x)
{
int top=0,i;
for (i=x;!Is_root(i);i=f[i]) stack[++top]=i;
stack[++top]=i;
for (i=top;i>=1;i--) pushdown(stack[i]);
for (;!Is_root(x);rotate(x))
if (!Is_root(f[x])) rotate(get(f[x])==get(x)?f[x]:x);
}
void access(int x)
{
int t=0;
for (;x;t=x,x=f[x])
{
splay(x);
ch[x][1]=t;
updata(x);
}
}
void reverse(int x)
{
access(x);
splay(x);
deltaz[x]^=1;
}
void Link(int x,int y)
{
reverse(x);
f[x]=y;
splay(x);
}
void Cut(int x,int y)
{
reverse(x);
access(y); splay(y);
ch[y][0]=f[x]=0;
}
int qurry(int x,int y)
{
reverse(x);
access(y);
splay(y);
return sum[y];
}
int main()
{
int n,q,i;
scanf("%d%d",&n,&q);
for (i=1;i<=n;i++) key[i]=deltac[i]=size[i]=1;
for (i=1;i<n;i++)
{
int x,y;
scanf("%d%d",&x,&y);
Link(x,y);
}
while (q--)
{
char st[5];int u,v,c,u1,v1,u2,v2;
scanf("%s",st);
if (st[0]=='+')
{
scanf("%d%d%d",&u,&v,&c);
reverse(u); access(v);
splay(v);
mark(v,c,1);
}
else if (st[0]=='-')
{
scanf("%d%d%d%d",&u1,&v1,&u2,&v2);
Cut(u1,v1); Link(u2,v2);
}
else if (st[0]=='*')
{
scanf("%d%d%d",&u,&v,&c);
reverse(u); access(v);
splay(v);
mark(v,0,c);
}
else
{
scanf("%d%d",&u,&v);
printf("%d\n",qurry(u,v));
}
}
}