"Luogu P3178" [HAOI2015]ツリーの動作

点の数が存在する\(N \)木、ポイント\(1 \)ルート、右側ツリーポイントを有するもの。そして、そこに\(M \)の操作、3種類に分け:

  • アクション1:置くノードが\(X \)ポイントの右に増加し\(A \)
  • 操作2:ノード\(X \)右サブツリー根ざした点のすべての点で増加している\(A \)
  • 操作3:ノードが要求し\(X \)すべての点および経路の重みのルートにポイント。

Luogu

分析

私たちは、木の使用を問う(\ DFS)\ツリーラインで直接シーケンスは、その後、一連の質問に変換され、解決することができます。

右側ルートと元のツリーの点で点までツリーラインの各リーフノードを考えます。シングルポイント修飾のために、現在のノードが追加(A \)\、それおよびそのサブツリーにおけるノード及びルートに右点が増加する(\ A)を\値の増加場合、サブツリー全体を変更するための\(A \) 次いで\(Xは\)にサブツリーその中に回答ノードの量を増加させる\(X \)パス上のノードのそして、\(\)製品、提供\(dep_i \)\(I \)の深さ、上部と答えです\(\タイムズ(dep_u-dep_x + 1)\)、\ (U \)ある\(Xは\)サブツリー内で、便宜上、我々は式中にノード(\回(1- \ \ dep_x)) 及び(\回\ dep_u)\、二つの部分に(\ \回(1-dep_x)\)尋ねプラス際、マーカ線分ツリーでマーク)(A \タイムズdep_u \ \

コード

#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;
}

おすすめ

転載: www.cnblogs.com/hlw1/p/12286038.html