点分树模板求调,悬2关
查看原帖
点分树模板求调,悬2关
386547
Infter楼主2024/4/4 15:55

注:starch_tree 即点分树

#include <bits/stdc++.h>
using namespace std;

constexpr int MAXN = 3e5 + 5;

#define int long long

//* O(1) Get Distance

vector<int> G[MAXN];
int st[MAXN][25], cnt, pos[MAXN], dep[MAXN];

void dfs(int u, int pa) {
    st[++cnt][0] = u;
    pos[u] = cnt;
    for (int v : G[u]) {
        if (v == pa)
            continue;
        dep[v] = dep[u] + 1;
        dfs(v, u);
        st[++cnt][0] = u;
    }
}

int cmp(int u, int v) {
    if (dep[u] < dep[v])
        return u;
    else
        return v;
}

void build_st() {
    for (int j = 1; (1 << j) < cnt; j++)
        for (int i = 1; i + (1 << j) <= cnt; i++)
            st[i][j] = cmp(st[i][j - 1], st[i + (1 << j - 1)][j - 1]);
}

int ask_dis(int u, int v) {
    int x = u, y = v;
    u = pos[u];
    v = pos[v];
    if (u > v)
        swap(u, v);
    int len = __lg(v - u + 1);
    int lca = cmp(st[u][len], st[v - (1 << len) + 1][len]);
    return dep[x] + dep[y] - 2 * dep[lca];
}

//* Fenwick

struct Fenwick {
    int n;
    vector<long long> c;

    void init(int _n) {
        n = _n;
        c.resize(n + 1);
    }

    int lowbit(int x) {
        return x & (-x);
    }

    void update(int x, long long k) {
        x++;
        for (int i = x; i <= n; i += lowbit(i)) {
            c[i] += k;
        }
    }

    long long query(int x) {
        x++;
        long long res = 0;
        if (x > n)
            x = n;
        for (int i = x; i >= 1; i -= lowbit(i))
            res += c[i];
        return res;
    }
} fenwick[2][MAXN];

//* Starch Tree

constexpr int INF = 0x3f3f3f3f;

int mn, rt, sz[MAXN], all, fa[MAXN];
bool vis[MAXN];

void findrt(int u, int pa) {
    int mx = 0;
    sz[u] = 1;
    for (int v : G[u]) {
        if (v == pa || vis[v])
            continue;
        findrt(v, u);
        sz[u] += sz[v];
        mx = max(mx, sz[v]);
    }
    mx = max(mx, all - sz[u]);
    if (mx < mn) {
        mn = mx;
        rt = u;
    }
}

void build_starch_tree(int u) {
    vis[u] = 1;
    sz[u] = all + 1;
    fenwick[0][u].init(sz[u]);
    fenwick[1][u].init(sz[u]);
    for (int v : G[u]) {
        if (vis[v])
            continue;
        all = sz[v];
        rt = 0;
        mn = INF;
        findrt(v, 0);
        fa[rt] = u;
        build_starch_tree(rt);
    }
}

int query(int u, int v) {
    int ans = fenwick[0][u].query(v);
    for (int i = u; fa[i]; i = fa[i]) {
        int dis = ask_dis(u, fa[i]);
        if (v >= dis)
            ans += fenwick[0][fa[i]].query(v - dis) - fenwick[1][i].query(v - dis);
    }
    return ans;
}

void modify(int u, int v) {
    for (int i = u; i; i = fa[i]) {
        fenwick[0][i].update(ask_dis(u, i), v);
    }
    for (int i = u; fa[i]; i = fa[i])
        fenwick[1][i].update(ask_dis(u, fa[i]), v);
}

//* Main

int n, m, val[MAXN];

signed main() {
    ios::sync_with_stdio(false);
    cin.tie(0);
    cout.tie(0);

    cin >> n >> m;
    for (int i = 1; i <= n; i++)
        cin >> val[i];
    for (int i = 1; i < n; i++) {
        int u, v;
        cin >> u >> v;
        G[u].push_back(v);
        G[v].push_back(u);
    }

    dfs(1, -1);
    build_st();
    all = n;
    mn = INF;
    findrt(1, 0);
    build_starch_tree(rt);

    for (int i = 1; i <= n; i++)
        modify(i, val[i]);
    // cerr << "OK" << endl;

    int lastans = 0;
    while (m--) {
        int opt, x, y;
        cin >> opt >> x >> y;
        x ^= lastans;
        y ^= lastans;
        if (opt == 0) {
            cout << (lastans = query(x, y)) << endl;
        } else {
            modify(x, y - val[x]);
            val[x] = y;
            lastans = 0;
        }
    }

    return 0;
}
2024/4/4 15:55
加载中...