星系探索 题解
题面
维护有根点权树,支持
- 换父亲(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;
}
以下是博客签名,正文无关
本文来自博客园,作者:Jijidawang,转载请注明原文链接:https://www.cnblogs.com/CDOI-24374/p/15912097.html
版权声明:本作品采用「署名-非商业性使用-相同方式共享 4.0 国际」许可协议(CC BY-NC-SA 4.0)进行许可。看完如果觉得有用请点个赞吧 QwQ