dfs序是指:每个节点在dfs深度优先遍历中的进出栈的时间序列。
如图,当我们维护一个时间戳,即每个节点进栈与出栈的时间,便可以把树上问题转换为区间问题。
例题如下:
当我们需要对树上问题进行区间求和的时候,如果我们可以把树上问题转为区间问题,便可以很方便的利用数组数组以及线段树去维护序列,
#include#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; } } }



