这道题有没有可能用 LCT 维护子树信息水过去(
查看原帖
这道题有没有可能用 LCT 维护子树信息水过去(
137603
zhiyangfanshotacon楼主2021/11/18 09:30

RT 初学 LCT 维护子树信息,估计会有很多问题,比如样例都过不去,但我觉得这个整体思路应该能写,大概思路就是用虚子树维护个子树权值和,然后还用虚子树每个点维护一下它所有子树的权值和的平方,最后询问的时候 makeroot\rm makeroot 一下。求一个 LCT 带师解答。

为啥在 NOIp 之前做这种题?属于是摆了。

#include <cstdio>
#include <algorithm>
const int N = 2e5 + 10; typedef long long ll; int st[N], tp;
struct LCT
{
	#define Fa(x) (node[x].fa)
	#define Ls(x) (node[x].ch[0])
	#define Rs(x) (node[x].ch[1])
	struct Splay{ int fa, ch[2], sum, ssum, w, revTag; ll ans, sans; }node[N];
	void pushup(int x)
	{
		node[x].sum = node[Ls(x)].sum + node[Rs(x)].sum + node[x].w + node[x].ssum;
		node[x].ans = node[Ls(x)].ans + node[Rs(x)].ans + node[x].sans + (ll)node[x].sum * node[x].sum;
	}
	void reverse(int x) { std::swap(Ls(x), Rs(x)); node[x].revTag ^= 1; }
	void pushdown(int x)
	{
		if (!node[x].revTag) return ;
		if (Ls(x)) reverse(Ls(x)); if (Rs(x)) reverse(Rs(x));
		node[x].revTag = 0;
	}
	int get(int x) { return Rs(Fa(x)) == x; }
	int nRoot(int x) { return Rs(Fa(x)) == x || Ls(Fa(x)) == x; }
	void rotate(int x)
	{
		int fa = Fa(x), gf = Fa(fa), d = get(x), dd = get(fa);
		if (nRoot(fa)) node[gf].ch[dd] = x;
		node[fa].ch[d] = node[x].ch[d ^ 1]; Fa(node[x].ch[d ^ 1]) = fa;
		node[x].ch[d ^ 1] = fa; Fa(fa) = x; Fa(x) = gf;
		pushup(fa); pushup(x);
	}
	void splay(int x)
	{
		int y = st[tp = 1] = x;
		while (nRoot(y)) st[++tp] = y = Fa(y);
		while (tp) pushdown(st[tp--]);
		for (; nRoot(x); rotate(x))
			if (nRoot(Fa(x))) rotate(get(x) == get(Fa(x)) ? Fa(x) : x);
		pushup(x);
	}
	void access(int x)
	{
		int y = 0;
		while (x)
		{	
			splay(x);
			if (Rs(x))
			{
				node[x].ssum += node[Rs(x)].sum;
				node[x].sans += node[Rs(x)].ans;
			}
			Rs(x) = y;
			if (y)
			{
				node[x].ssum -= node[y].sum;
				node[x].sans -= node[y].ans;
			}
			pushup(x); x = Fa(y = x);
		}
	}
	void makeroot(int x) { access(x); splay(x); reverse(x); }
	void link(int x, int y)
	{
		access(y); splay(y); splay(x); Fa(x) = y; 
		node[y].ssum += node[x].sum;
		node[y].sans += node[x].ans;
		pushup(y);
	}
}lct;
int a[N], b[N];
int main()
{
	int n, q; scanf("%d%d", &n, &q);
	for (int i = 1; i < n; ++i) scanf("%d%d", &a[i], &b[i]);
	for (int i = 1; i <= n; ++i) scanf("%d", &lct.node[i].w);
	for (int i = 1; i < n; ++i) lct.link(a[i], b[i]);
	for (int i = 1, opt, x, y; i <= q; ++i)
	{
		scanf("%d%d", &opt, &x);
		if (opt == 2) lct.makeroot(x), printf("%lld\n", lct.node[x].ans);
		else scanf("%d", &y), lct.node[x].w = y, lct.splay(x);
	}
	return 0;
}

QAQ

2021/11/18 09:30
加载中...