dfs序是指:每个节点在dfs深度优先遍历中的进出栈的时间序列。
如图,当我们维护一个时间戳,即每个节点进栈与出栈的时间,便可以把树上问题转换为区间问题。
例题如下:
当我们需要对树上问题进行区间求和的时候,如果我们可以把树上问题转为区间问题,便可以很方便的利用数组数组以及线段树去维护序列,
#include<bits/stdc++.h>
#define int long long
using namespace std;
const int N = 1e6 + 10;
const int M = N * 2;
int n,m,k;
int vv[N];
int h[N],e[M],ne[M],idx;
int c[N];
int l[N];
int r[N];
int ti;
int ask(int x)
{
int ans = 0;
for(; x ; x -= (x & - x)) ans += c[x];
return ans ;
}
void ad(int x,int y)
{
for(; x <= N; x+= x & - x) c[x] += y;
}
void add (int a,int b)
{
e[idx]=b;
ne[idx]=h[a];
h[a]=idx++;
}
void dfs(int u,int fa)
{
l[u] = ++ti;
for(int i = h[u];i != - 1 ; i = ne[i])
if(e[i] != fa) dfs(e[i],u);
r[u] = ti;
}
signed main()
{
memset(h,-1,sizeof h);
cin >> n >> m >> k;
for(int i = 1 ; i <= n ; i++) cin >> vv[i];
int x,y;
for(int i = 1; i < n ; i++)
{
cin >> x >> y;
add(x,y);
add(y,x);
}
dfs(k,0);
int op,u,v;
for(int i = 1 ; i <= n ; i++)
{
ad(l[i],vv[i]);
}
for(int i = 1 ; i <= m ; i++)
{
cin >> op;
if(op == 1)
{
cin >> u >> v;
ad(l[u],v);
}
else if(op == 2)
{
cin >> u;
cout << ask(r[u]) - ask(l[u] - 1) << endl;
}
}
}