题意就是将BZOJ1798的数列的操作改成了树的操作。大体相似,用 Link -Cut-Tree 维护。
貌似细节不少的样子呢……一定要细心……当年这道题调了好久的说……//其实是我太渣了
update 函数里忘记了加 maintain(x) 的错误 QAQ
同时这也是我写的少数数组版代码之一//数组写成这个样子ch[fa[f]][check(f)]也是真心不爽嗯
下面是我的数组版代码~~
#include <cstdio>
#include <cstring>
#include <iostream>
#include <algorithm>
using namespace std;
#define mod 51061
#define N 100005
int n,q,ch[N][2],fa[N],rev[N];
unsigned int val[N],size[N],sum[N],mul[N],add[N];
inline bool root(int x)
{
return ch[fa[x]][0]!=x&&ch[fa[x]][1]!=x;
}
inline bool check(int x)
{
return ch[fa[x]][1]==x;
}
void reverse(int x)
{
rev[x]^=1;
rev[ch[x][0]]^=1;
rev[ch[x][1]]^=1;
swap(ch[x][0],ch[x][1]);
}
void calc(int x,unsigned int y,unsigned int z)
{
val[x]=(val[x]*y+z)%mod;
sum[x]=(sum[x]*y+size[x]*z)%mod;
mul[x]=(mul[x]*y)%mod;
add[x]=(add[x]*y+z)%mod;
}
void pushdown(int x)
{
if(!root(x))
pushdown(fa[x]);
if(rev[x])
reverse(x);
if(ch[x][0]) calc(ch[x][0],mul[x],add[x]);
if(ch[x][1]) calc(ch[x][1],mul[x],add[x]);
mul[x]=1,add[x]=0;
}
void maintain(int x)
{
sum[x]=(sum[ch[x][0]]+sum[ch[x][1]]+val[x])%mod;
size[x]=(size[ch[x][0]]+size[ch[x][1]]+1)%mod;
}
void rotate(int x)
{
int f=fa[x],d=!check(x);
ch[f][d^1]=ch[x][d]; fa[ch[x][d]]=f; ch[x][d]=f;
if(!root(f)) ch[fa[f]][check(f)]=x;
fa[x]=fa[f]; fa[f]=x;
maintain(f);maintain(x);
}
void splay(int x)
{
pushdown(x);
while(!root(x))
{
if(!root(fa[x]))
check(fa[x])^check(x)?rotate(x):rotate(fa[x]);
rotate(x);
}
}
void access(int x)
{
int y=0;
while(x) splay(x),ch[x][1]=y,maintain(x),x=fa[y=x];
}
void makeroot(int x)
{
access(x);splay(x);
rev[x]^=1;
}
void link(int x,int y)
{
makeroot(x);
fa[x]=y;
}
void cut(int x,int y)
{
makeroot(x);
access(y);splay(y);
ch[y][0]=fa[x]=0;
}
int main()
{
cin>>n>>q;
for(int i=1;i<=n;i++)
val[i]=size[i]=sum[i]=mul[i]=1;
for(int x,y,i=1;i<n;i++)
scanf("%u%u",&x,&y),
link(x,y);
while(q--)
{
char ch[5];int u,v,x,y;
scanf("%s",ch);
if(ch[0]=='+')
{
scanf("%d%d%d",&u,&v,&x);
makeroot(u);
access(v);splay(v);
calc(v,1,x);
}
else if(ch[0]=='-')
{
scanf("%d%d%d%d",&u,&v,&x,&y);
cut(u,v);link(x,y);
}
else if(ch[0]=='*')
{
scanf("%d%d%d",&u,&v,&x);
makeroot(u);
access(v);splay(v);
calc(v,x,0);
}
else if(ch[0]=='/')
{
scanf("%d%d",&u,&v);
makeroot(u);
access(v);splay(v);
printf("%u\n",sum[v]);
}
}
return 0;
}