洛谷P6329 【模板】点分树 / 震波 题解 动态点分治/点分树 模板题
题目链接:https://www.luogu.com.cn/problem/P6329
思路全部来自 OI WIKI:https://oi.wiki/graph/dynamic-tree-divide/
按照自己的码风写了一下。
示例程序:
#include <bits/stdc++.h>
using namespace std;
const int maxn = 1e5 + 5, maxm = maxn * 200;
int n, m, value[maxn], rt, fa[maxn], ans;
bool vis[maxn];
vector<int> g[maxn];
struct LCA {
int dep[maxn], fa[maxn][17];
void dfs(int u, int p) {
fa[u][0] = p;
dep[u] = dep[p] + 1;
for (auto v : g[u])
if (v != p)
dfs(v, u);
}
void build() {
dfs(1, 0);
for (int i = 1; i < 17; i++)
for (int u = 1; u <= n; u++)
fa[u][i] = fa[ fa[u][i-1] ][i-1];
}
int lca(int x, int y) {
if (dep[x] < dep[y])
swap(x, y);
for (int i = 16; i >= 0; i--) {
int p = fa[x][i];
if (dep[p] >= dep[y]) x = p;
}
if (x == y)
return x;
for (int i = 16; i >= 0; i--)
if (fa[x][i] != fa[y][i])
x = fa[x][i], y = fa[y][i];
return fa[x][0];
}
int dis(int x, int y) {
return dep[x] + dep[y] - 2 * dep[lca(x, y)];
}
} lca;
struct Segtree {
int rt[maxn], ls[maxm], rs[maxm], tr[maxm], idx;
void push_up(int u) {
tr[u] = tr[ ls[u] ] + tr[ rs[u] ];
}
void update(int p, int val, int l, int r, int &u) {
if (!u) u = ++idx;
if (l == r) {
tr[u] += val;
return;
}
int mid = l + r >> 1;
(p <= mid) ? update(p, val, l, mid, ls[u]) : update(p, val, mid+1, r, rs[u]);
push_up(u);
}
int query(int L, int R, int l, int r, int u) {
if (!u) return 0;
if (L <= l && r <= R)
return tr[u];
int res = 0, mid = l + r >> 1;
if (L <= mid)
res += query(L, R, l, mid, ls[u]);
if (R > mid)
res += query(L, R, mid+1, r, rs[u]);
return res;
}
} info_fa, info_me;
int get_sz(int u, int p) {
if (vis[u]) return 0;
int sz = 1;
for (auto v : g[u])
if (v != p)
sz += get_sz(v, u);
return sz;
}
int get_wc(int u, int p, int tot, int &wc) {
if (vis[u]) return 0;
int sz = 1, mx = 0;
for (auto v : g[u]) {
if (v != p) {
int tmp = get_wc(v, u, tot, wc);
sz += tmp;
mx = max(mx, tmp);
}
}
mx = max(mx, tot - sz);
if (mx <= tot / 2)
wc = u;
return sz;
}
void dfs_me(int u, int p, int d, int x) {
if (vis[u]) return;
info_me.update(d, value[u], 0, n, info_me.rt[x]);
for (auto v : g[u])
if (v != p)
dfs_me(v, u, d+1, x);
}
void dfs_fa(int u, int p, int d, int x) {
if (vis[u]) return;
info_fa.update(d, value[u], 0, n, info_fa.rt[x]);
for (auto v : g[u])
if (v != p)
dfs_fa(v, u, d+1, x);
}
void pre(int u) {
dfs_me(u, 0, 0, u);
vis[u] = true;
for (auto v : g[u]) {
if (vis[v]) continue;
int x;
get_wc(v, u, get_sz(v, u), x);
dfs_fa(v, u, 1, x);
fa[x] = u;
pre(x);
}
}
int main() {
scanf("%d%d", &n, &m);
for (int i = 1; i <= n; i++) {
scanf("%d", value + i);
}
for (int i = 1, u, v; i < n; i++) {
scanf("%d%d", &u, &v);
g[u].push_back(v);
g[v].push_back(u);
}
lca.build();
get_wc(1, 0, n, rt);
pre(rt);
for (int i = 0, op; i < m; i++) {
scanf("%d", &op);
if (op == 0) { // 0 x k
int x, k;
scanf("%d%d", &x, &k);
x ^= ans;
k ^= ans;
ans = info_me.query(0, k, 0, n, info_me.rt[x]);
for (int u = x; fa[u]; u = fa[u]) {
int p = fa[u];
int d = lca.dis(x, p);
if (d <= k) {
ans += info_me.query(0, k-d, 0, n, info_me.rt[p]);
ans -= info_fa.query(0, k-d, 0, n, info_fa.rt[u]);
}
}
printf("%d\n", ans);
}
else { // 1 x y
int x, y;
scanf("%d%d", &x, &y);
x ^= ans;
y ^= ans;
info_me.update(0, -value[x], 0, n, info_me.rt[x]);
info_me.update(0, y, 0, n, info_me.rt[x]);
for (int u = x; fa[u]; u = fa[u]) {
int p = fa[u];
int d = lca.dis(x, p);
info_me.update(d, -value[x], 0, n, info_me.rt[p]);
info_me.update(d, y, 0, n, info_me.rt[p]);
info_fa.update(d, -value[x], 0, n, info_fa.rt[u]);
info_fa.update(d, y, 0, n, info_fa.rt[u]);
}
value[x] = y;
}
}
return 0;
}
浙公网安备 33010602011771号