题目:
给你一棵个结点的有根树,为根。结点有点权。个操作:
:结点权值,的儿子们权值,的孙子们...以此类推;
:询问当前的点权;
做法:
序:从根出发经过结点的顺序,每个结点只加一次,长度。
欧拉序:从根出发绕回根沿途经过的结点的顺序,每进入结点加一次,长度。
这题的更新操作中,我们发现其在欧拉序中是有规律的。
比如我们要给号结点,在欧拉序中找到出现最左和最右的位置,这个区间就是以为根的整棵子树,我们发现按+-+-的顺序更新这个区间的点权正好满足题目要求。
再比如我们要给号结点。
对应位置的更新完全是正确的。所以我们可以用线段树维护这个在欧拉序上+-+-的区间更新,以及单点查询。
代码:
#include <bits/stdc++.h> #define lson rt<<1 #define rson rt<<1|1 #define IOS ios::sync_with_stdio(false), cin.tie(0) #define debug(a) cout << #a ": " << a << endl using namespace std; typedef long long ll; const int N = 2e5 + 7; int n, m, a[N], dfn[N<<1], tag, in[N], out[N]; vector<int> g[N]; int T[N<<3], laz[N<<3]; void dfs(int u, int p){ dfn[++tag] = u, in[u] = tag; for (auto &v : g[u]) if (v != p){ dfs(v, u); dfn[++tag] = u; } out[u] = tag; } void pushdown(int l, int r, int rt){ int val = laz[rt]; laz[rt] = 0; int mid = (l+r) >> 1, f = ((mid-l)&1 ? 1 : -1); T[lson] += val, laz[lson] += val; T[rson] += f*val, laz[rson] += f*val; } void build(int l, int r, int rt){ if (l == r){ T[rt] = a[dfn[l]]; return; } int mid = (l+r) >> 1; build(l, mid, lson); build(mid+1, r, rson); } void update(int L, int R, int val, int l, int r, int rt){ if (L == l && r == R){ T[rt] += val; laz[rt] += val; return; } if (laz[rt] != 0) pushdown(l, r, rt); int mid = (l+r) >> 1; if (R <= mid){ update(L, R, val, l, mid, lson); }else if (L > mid){ update(L, R, val, mid+1, r, rson); }else{ update(L, mid, val, l, mid, lson); update(mid+1, R, ((mid-L)&1 ? val : -val), mid+1, r, rson); } } int query(int x, int l, int r, int rt){ if (l == r) return T[rt]; if (laz[rt] != 0) pushdown(l, r, rt); int mid = (l+r) >> 1; if (x <= mid) return query(x, l, mid, lson); if (x > mid) return query(x, mid+1, r, rson); } int main(void){ scanf("%d%d", &n, &m); for (int i = 1; i <= n; ++i) scanf("%d", &a[i]); for (int i = 0; i < n-1; ++i){ int u, v; scanf("%d%d", &u, &v); g[u].push_back(v); g[v].push_back(u); } dfs(1, 0); build(1, tag, 1); while (m--){ int op, x, val; scanf("%d%d", &op, &x); if (op == 1){ scanf("%d", &val); update(in[x], out[x], val, 1, tag, 1); }else{ printf("%d\n", query(in[x], 1, tag, 1)); } } return 0; }