我的 cut
函数需要先 pushDown
才能 pushUp
,不然会出错;但是我认为在 split
的时候标记应该已经下传完了qwq
inline void cut(int x, int y)
{
split(x, y);
fa(x) = lc(y) = 0;
pushDown(y);
pushUp(y);
}
想请教一下这是什么原因
#include <cstdio>
#include <algorithm>
using namespace std;
const int MAXN = 100010;
const int MOD = 51061;
inline int add(int a, int b) {return (a+=b)>=MOD?a-MOD:a;}
inline int mul(int a, int b) {return 1ll*a*b%MOD;}
inline void inc(int& a, int b) {a = add(a, b);}
inline void mlt(int& a, int b) {a = mul(a, b);}
int n, m;
struct node{
int ch[2], val, sum, siz, fa, mulTag, addTag;
bool rev;
}t[MAXN];
#define lc(x) t[x].ch[0]
#define rc(x) t[x].ch[1]
#define fa(x) t[x].fa
#define rev(x) t[x].rev
#define val(x) t[x].val
#define sum(x) t[x].sum
#define siz(x) t[x].siz
#define mt(x) t[x].mulTag
#define at(x) t[x].addTag
inline bool ident(int x) {return rc(fa(x)) == x;}
inline void connect(int x, int f, int c) {t[fa(x)=f].ch[c] = x;}
inline void pushUp(int x)
{
siz(x) = siz(lc(x)) + siz(rc(x)) + 1;
sum(x) = add(add(sum(lc(x)), sum(rc(x))), val(x));
}
inline bool nroot(int x) {return rc(fa(x)) == x || lc(fa(x)) == x;}
inline void pushadd(int x, int v)
{
inc(sum(x), mul(siz(x), v));
inc(val(x), v);
inc(at(x), v);
}
inline void pushmul(int x, int v)
{
mlt(sum(x), v);
mlt(val(x), v);
mlt(mt(x), v);
mlt(at(x), v);
}
inline void pushrev(int x)
{
swap(lc(x), rc(x));
rev(x) ^= 1;
}
inline void pushDown(int x)
{
if(mt(x) != 1)
{
if(lc(x)) pushmul(lc(x), mt(x));
if(rc(x)) pushmul(rc(x), mt(x));
mt(x) = 1;
}
if(at(x))
{
if(lc(x)) pushadd(lc(x), at(x));
if(rc(x)) pushadd(rc(x), at(x));
at(x) = 0;
}
if(rev(x))
{
if(lc(x)) pushrev(lc(x));
if(rc(x)) pushrev(rc(x));
rev(x) = 0;
}
}
void pushall(int x)
{
if(nroot(x)) pushall(fa(x));
pushDown(x);
}
inline void rotate(int x)
{
int y = fa(x), z = fa(y), k = ident(x), w = t[x].ch[k^1];
if(w) fa(w) = y;
t[y].ch[k] = w;
fa(x) = z;
if(nroot(y)) t[z].ch[ident(y)] = x;
connect(y, x, k^1);
pushUp(y); pushUp(x);
}
inline void splay(int x)
{
pushall(x);
while(nroot(x))
{
int y = fa(x);
if(nroot(y)) rotate(ident(x)^ident(y)?x:y);
rotate(x);
}
}
inline void access(int x)
{
for(int y=0;x;x=fa(y=x))
splay(x), rc(x) = y, pushUp(x);
}
inline void makeroot(int x)
{
access(x); splay(x); pushrev(x);
}
inline void split(int x, int y)
{
makeroot(x); access(y); splay(y);
}
inline void link(int x, int y)
{
makeroot(x);
fa(x) = y;
}
inline void cut(int x, int y)
{
split(x, y);
fa(x) = lc(y) = 0;
pushDown(y);
pushUp(y);
}
inline void updAdd(int x, int y, int v)
{
split(x, y);
pushadd(y, v);
}
inline void updMul(int x, int y, int v)
{
split(x, y);
pushmul(y, v);
}
inline int qrySum(int x, int y)
{
split(x, y);
return sum(y);
}
#undef lc
#undef rc
#undef fa
#undef rev
#undef val
#undef sum
#undef siz
#undef mt
#undef at
int main()
{
scanf("%d%d",&n,&m);
for(int i=1;i<=n;i++) t[i].mulTag = t[i].siz = t[i].val = 1;
for(int i=1;i<n;i++)
{
int u, v;
scanf("%d%d",&u,&v);
link(u, v);
}
while(m--)
{
char opt[5]; int x, y, v;
scanf("%s%d%d",opt+1,&x,&y);
if(opt[1] == '+') scanf("%d",&v), updAdd(x, y, v);
else if(opt[1] == '*') scanf("%d",&v), updMul(x, y, v);
else if(opt[1] == '/') printf("%d\n",qrySum(x, y));
else cut(x, y), scanf("%d%d",&x,&y), link(x, y);
}
return 0;
}