题目:
给你一棵个结点的有根树,
为根。结点有点权。
个操作:
:结点
权值
,
的儿子们权值
,
的孙子们
...以此类推;
:询问
当前的点权;
做法:
序:从根出发
经过结点的顺序,每个结点只加一次,长度
。
欧拉序:从根出发绕回根沿途经过的结点的顺序,每进入结点加一次,长度
。
这题的更新操作中,我们发现其在欧拉序中是有规律的。
比如我们要给号结点
,在欧拉序中找到
出现最左和最右的位置,这个区间就是以
为根的整棵子树,我们发现按+-+-的顺序更新这个区间的点权正好满足题目要求。
再比如我们要给号结点
。
对应位置的更新完全是正确的。所以我们可以用线段树维护这个在欧拉序上+-+-的区间更新,以及单点查询。
代码:
#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;
}
京公网安备 11010502036488号