星系探索 题解

题面

BZOJ #3786

维护有根点权树,支持

  • 换父亲(link-cut)
  • 子树加
  • 点到根路径点权和

题解

原来是个 伪 · Euler Tour Tree (ETT)

伪 ETT 这么容易口胡的吗,,,

维护 DFS 括号序(像差分一样),然后 link-cut 就是区间平移 .

做完了,Splay 维护即可 .

当然也可以不用 Splay,……

代码

不咕了,代码来了

// ??????????
// version 114.514

#include <iostream>
#include <algorithm>
#include <cstring>
#include <cstdio>
#include <ctime>
#include <climits>
#include <vector>
#include <queue>
#include <cmath>
#include <map>
#include <set>
#include <bitset>
using namespace std;
const int N = 314159;
typedef long long ll;
typedef long double ld;
typedef unsigned long long ull;
typedef pair<int, int> pii;
template<typename T>
inline int chkmin(T& a, const T& b){if (a > b) a = b; return a;}
template<typename T>
inline int chkmax(T& a, const T& b){if (a < b) a = b; return a;}
vector<int> g[N];
int n, w[N];
inline void addedge(int u, int v){g[u].emplace_back(v);}
inline void ade(int u, int v){addedge(u, v); addedge(v, u);}
int dfn[N][2], typ[N], tot = 1;
struct Splay
{
	int root, fa[N], ch[N][2], L[N], R[N], cc;
	ll val[N], sum[N], laz[N];
	inline void pushup(int u)
	{
		sum[u] = sum[ch[u][0]] + sum[ch[u][1]] + val[u];
		L[u] = L[ch[u][0]] + L[ch[u][1]] + (typ[u] == 1);
		R[u] = R[ch[u][0]] + R[ch[u][1]] + (typ[u] == -1);
	}
	inline void pushdown(int u)
	{
		if (!laz[u]) return ;
		if (ch[u][0])
		{
			laz[ch[u][0]] += laz[u];
			val[ch[u][0]] += laz[u] * typ[ch[u][0]];
			sum[ch[u][0]] += laz[u] * (L[ch[u][0]] - R[ch[u][0]]);
		}
		if (ch[u][1])
		{
			laz[ch[u][1]] += laz[u];
			val[ch[u][1]] += laz[u] * typ[ch[u][1]];
			sum[ch[u][1]] += laz[u] * (L[ch[u][1]] - R[ch[u][1]]);
		}
		laz[u] = 0;
	}
	inline bool son(int u){return u == ch[fa[u]][1];}
	inline void rotate(int x)
	{
		int y = fa[x], z = fa[y], chk = son(x);
		pushdown(y); pushdown(x);
		ch[z][son(y)] = x; fa[x] = z;
		ch[y][chk] = ch[x][chk^1]; fa[ch[x][chk^1]] = y;
		ch[x][chk^1] = y; fa[y] = x;
		pushup(y); pushup(x);
	}
	inline void splay(int x, int to = 0)
	{
		while (fa[x] != to)
		{
			int y = fa[x];
			if (fa[y] != to) rotate(son(y) == son(x) ? y : x);
			rotate(x);
		} if (!to) root = x;
	}
	inline void build(int l, int r, int f)
	{
		if (l > r) return ;
		int mid = (l + r) >> 1;
		fa[mid] = f; ch[f][mid > f] = mid;
		if (l == r){sum[mid] = val[mid]; L[mid] = (typ[mid]==1); R[mid] = !L[mid]; return ;} // p
		build(l, mid-1, mid); build(mid+1, r, mid);
		pushup(mid);
	}
	inline int prev(int u){splay(u); u = ch[root][0]; while (ch[u][1]) u = ch[u][1]; return u;}
	inline int succ(int u){splay(u); u = ch[root][1]; while (ch[u][0]) u = ch[u][0]; return u;}
	inline void get(int l, int r)
	{
		int p = prev(l), s = succ(r);
		splay(p); splay(s, p);
	}
	inline ll query(int u){get(dfn[1][0], dfn[u][0]); return sum[ch[ch[root][1]][0]];}
	inline void change(int x, int f)
	{
		get(dfn[x][0], dfn[x][1]);
		int pos = ch[ch[root][1]][0];
		fa[pos] = 0; ch[ch[root][1]][0] = 0;
		pushup(ch[root][1]); pushup(root);
		int _ = succ(dfn[f][0]); splay(_, root);
		ch[ch[root][1]][0] = pos; fa[pos] = ch[root][1];
		pushup(ch[root][1]); pushup(root);
	}
	inline void add(int x, int v)
	{
		get(dfn[x][0], dfn[x][1]);
		int u = ch[ch[root][1]][0];
		sum[u] += v * (L[u] - R[u]);
		val[u] += v * typ[u];
		laz[u] += v;
		pushup(ch[root][1]); pushup(root);
	}
	Splay(){root = cc = 0;}
}T;
void dfs(int u)
{
	dfn[u][0] = ++tot; typ[tot] = 1;
	for (int v : g[u]) dfs(v);
	dfn[u][1] = ++tot; typ[tot] = -1;
}
int main()
{
#ifndef ONLINE_JUDGE
	freopen("i.in", "r", stdin);
#endif
	scanf("%d", &n);
	for (int i=2, u; i<=n; i++) scanf("%d", &u), addedge(u, i);
	for (int i=1; i<=n; i++) scanf("%d", w+i);
	dfs(1);
	for (int i=1; i<=n; i++){T.val[dfn[i][0]] = w[i]; T.val[dfn[i][1]] = -w[i];}
	int ndc = n*2+2;
	T.build(1, ndc, 0); T.root = (ndc+1) * 2;
	ll m, p, q; char opt[2]; scanf("%lld", &m);
	while (m--)
	{
		scanf("%s%lld", opt, &p);
		if (*opt == 'Q') printf("%lld\n", T.query(p));            // Q (chain)
		else if (*opt == 'C') scanf("%lld", &q), T.change(p, q);  // C (link-cut)
		else scanf("%lld", &q), T.add(p, q);                      // F (subtree)
	} return 0;
}
posted @ 2022-02-19 10:57  Jijidawang  阅读(72)  评论(0编辑  收藏  举报
😅​