蒟蒻初学 LCT,有一事不明
查看原帖
蒟蒻初学 LCT,有一事不明
151601
Aphros楼主2021/2/14 09:42

我的 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;
}
2021/2/14 09:42
加载中...