"Luogu P3178" [HAOI2015] tree operation

There are a number of points to \ (N \) tree, point \ (1 \) as the root, the right side and the tree has a point. Then there \ (M \) operations, divided into three types:

  • Action 1: put a node \ (x \) increased point right \ (A \) .
  • Operation 2: The a node \ (X \) for all points of the right subtree rooted points are increased \ (A \) .
  • Operation 3: a node asks \ (X \) points to the root of the weights of all points and path.

Luogu

analysis

We question the use of the tree \ (dfs \) sequence is then converted into a sequence of questions can be resolved directly on the tree line.

Consider each leaf node of the tree line to point right at the point of the original tree to the root and. For single-point modification, the current node adds \ (A \) , then it and the node in its subtree and the right point to the root will increase \ (A \) . For modifying an entire subtree, if the increase in the value \ (A \) , then the \ (X \) increasing the amount of answers nodes within the subtree it to \ (X \) of nodes on the path and \ (a \) the product, provided \ (dep_i \) of \ (I \) depth, the top and the answer is \ (a \ Times (dep_u-dep_x +. 1) \) , \ (U \) is \ (X \) nodes within a subtree, for convenience, we formula into \ (a \ times (1- dep_x) \) and \ (a \ times dep_u \) in two parts, the \ (a \ times (1-dep_x) \) marked by the marker line segment tree, when asked plus \ (A \ Times dep_u \) .

Code

#include <bits/stdc++.h>

#define N 100003
#define ls o<<1
#define rs o<<1|1
#define ll long long

using namespace std;

int gi() {
    int x = 0, f = 1; char c = getchar();
    for ( ; !isdigit(c); c = getchar()) if (c == '-') f = -1;
    for ( ; isdigit(c); c = getchar()) x = x * 10 + (c ^ 48);
    return x * f;
}

int n, m, tot;
int nxt[N], hd[N], cnt;
int val[N], dep[N], dfn[N], st[N], ed[N];

struct SegmentTree {
    ll add[N << 2], mul[N << 2];
    void pushdown(int o) {
        add[ls] += add[o], add[rs] += add[o];
        mul[ls] += mul[o], mul[rs] += mul[o];
        add[o] = mul[o] = 0;
    }
    void modify(int o, int l, int r, int L, int R, ll x, ll y) {
        if (l > R || r < L) return;
        if (l >= L && r <= R) {
            add[o] += x, mul[o] += y;
            return;
        }
        pushdown(o);
        int mid = l + r >> 1;
        modify(ls, l, mid, L, R, x, y), modify(rs, mid + 1, r, L, R, x, y);
    }
    ll query(int o, int l, int r, int p) {
        if (l == r) return add[o] + 1ll * mul[o] * dep[dfn[p]];
        pushdown(o);
        int mid = l + r >> 1;
        if (p <= mid) return query(ls, l, mid, p);
        else return query(rs, mid + 1, r, p);
    }
} tr;

void insert(int u, int v) { nxt[u] = hd[v], hd[v] = u; }

void dfs(int u, int fa) {
    dep[u] = dep[fa] + 1, dfn[++tot] = u, st[u] = tot;
    for (int v = hd[u]; v; v = nxt[v]) dfs(v, u);
    ed[u] = tot;
}

int main() {
    int opt, x, a, u, v;
    n = gi(), m = gi();
    for (int i = 1; i <= n; ++i) val[i] = gi();
    for (int i = 1; i < n; ++i) {
        u = gi(), v = gi();
        insert(u, v);
    }
    dfs(1, 0);
    for (int i = 1; i <= n; ++i) tr.modify(1, 1, n, st[i], ed[i], val[i], 0);
    for (int i = 1; i <= m; ++i) {
        opt = gi(), x = gi();
        if (opt == 1) tr.modify(1, 1, n, st[x], ed[x], gi(), 0);
        else if (opt == 2) {
            a = gi();
            tr.modify(1, 1, n, st[x], ed[x], 1ll * a * (1 - dep[x]), a);
        }
        else printf("%lld\n", tr.query(1, 1, n, st[x]));
    }
    return 0;
}

Guess you like

Origin www.cnblogs.com/hlw1/p/12286038.html