参考题解

题目意思

第一行一个T,代表总操作数T,T<4e5
后面有T行,分三种情况。第一个数是1,生成一个新的节点挂在第二个数的子节点位置,编号为第几次操作1就是几。
第二种情况是第一个数为2,把第二个数以及全部子树权值都增加第三个数大小。
第三种情况是第一个数是3,直接输出第二个数的权值。

Solution

动态建树,以及区间改动,并不好实现。我们采取一种离线的做法。
在输入的时候,保存好操作信息,主要就是保存好下面代码中的b[i]数组。
用vector模拟建树,用DFS序表示每个节点掌控的数字下标范围。
操作2就是常规的树状数组区间改变。
在每次操作1中用另外的一个数组,初始化值为负的父节点权值,这样下次树状数组累加的时候就能初始化这个节点值为0了。

#pragma GCC target("avx,sse2,sse3,sse4,popcnt")
#pragma GCC optimize("O2,O3,Ofast,inline,unroll-all-loops,-ffast-math")
#include <bits/stdc++.h>
using namespace std;
#define js ios::sync_with_stdio(false);cin.tie(0); cout.tie(0)
#define all(__vv__) (__vv__).begin(), (__vv__).end()
#define endl "\n"
#define pai pair<int, int>
#define ms(__x__,__val__) memset(__x__, __val__, sizeof(__x__))
typedef long long ll; typedef unsigned long long ull; typedef long double ld;
inline ll read() { ll s = 0, w = 1; char ch = getchar(); for (; !isdigit(ch); ch = getchar()) if (ch == '-') w = -1; for (; isdigit(ch); ch = getchar())    s = (s << 1) + (s << 3) + (ch ^ 48); return s * w; }
inline void print(ll x, int op = 10) { if (!x) { putchar('0'); if (op)    putchar(op); return; }    char F[40]; ll tmp = x > 0 ? x : -x;    if (x < 0)putchar('-');    int cnt = 0;    while (tmp > 0) { F[cnt++] = tmp % 10 + '0';        tmp /= 10; }    while (cnt > 0)putchar(F[--cnt]);    if (op)    putchar(op); }
inline ll gcd(ll x, ll y) { return y ? gcd(y, x % y) : x; }
ll qpow(ll a, ll b) { ll ans = 1;    while (b) { if (b & 1)    ans *= a;        b >>= 1;        a *= a; }    return ans; }    ll qpow(ll a, ll b, ll mod) { ll ans = 1; while (b) { if (b & 1)(ans *= a) %= mod; b >>= 1; (a *= a) %= mod; }return ans % mod; }
inline int lowbit(int x) { return x & (-x); }
const int dir[][2] = { {0,1},{1,0},{0,-1},{-1,0},{1,1},{1,-1},{-1,1},{-1,-1} };
const int MOD = 1e9 + 7;
const int INF = 0x3f3f3f3f;

const int N = 4e5 + 7;
vector<int> g[N];
int l[N], r[N], val[N], cnt;


int c[N];
void add(int i, int x) {
    for (; i < N; i += lowbit(i))    c[i] += x;
}

int query(int i) {
    int ret = 0;
    for (; i; i -= lowbit(i))    ret += c[i];
    return ret;
}

int op[N], a[N], b[N];

void dfs(int u) {
    l[u] = ++cnt;
    for (auto it : g[u]) {
        dfs(it);
    }
    r[u] = cnt;
}

int main() {
    int T = read();
    for (int i = 1; i <= T; ++i) {
        op[i] = read(), a[i] = read();
        if (op[i] == 1) {
            g[a[i]].push_back(++cnt);
            b[i] = cnt;
        }
        else if (op[i] == 2)    b[i] = read();
    }
    cnt = 0;
    dfs(0);
    for (int i = 1; i <= T; ++i) {
        if (op[i] == 1)
            val[l[b[i]]] = -query(l[a[i]]);
        else if (op[i] == 2) {
            add(l[a[i]], b[i]);
            add(r[a[i]] + 1, -b[i]);
        }
        else
            print(val[l[a[i]]] + query(l[a[i]]));
    }
    return 0;
}