DFS序
dfs序是一种把树状结构改变为线段结构的操作,在之后用树状数组或线段树操作,怎么把树状数组改成线状呢?根据dfs搜索的先后,为其赋上新的值。
dfs之后的顺序是
A B E F K C G H I A B E F K C G H I ABEFKCGHI
123456789 1 2 3 4 5 6 7 8 9 123456789
A A A管辖的范围是 A − I = 1 − 9 A-I=1-9 A−I=1−9
B B B管辖的范围是 B − K = 2 − 5 B-K=2-5 B−K=2−5
以此类推
code
void dfs(ll root, ll fa)
{
l[root] = ++cnt;
for(ll i = head[root]; i; i = net[i])
{
if(ver[i] == fa)
continue;
dfs(ver[i], root);
}
r[root] = cnt;
}
之后的数字 x x x与 l [ x ] l[x] l[x]绑定(本身的值和 d f s dfs dfs后的值),他管辖的区间是 l [ x ] − r [ x ] l[x]-r[x] l[x]−r[x]
例题
code
#include<bits/stdc++.h>
using namespace std;
typedef long long ll;
const ll N = 2e6+5;
ll ver[N], head[N], net[N];
ll cnt, tot, n, m, k, val[N], l[N], r[N], tree[N];
void add(ll x, ll y)
{
ver[++tot] = y;
net[tot] = head[x];
head[x] = tot;
//edge[tot] = z;
}
void dfs(ll root, ll fa)
{
l[root] = ++cnt;
for(ll i = head[root]; i; i = net[i])
{
if(ver[i] == fa)
continue;
dfs(ver[i], root);
}
r[root] = cnt;
}
ll lowbit(ll x)
{
return (-x) & x;
}
void updata(ll x, ll value)
{
while(x <= n)
{
tree[x] += value;
x += lowbit(x);
}
}
ll query(ll x)
{
ll ans = 0;
while(x)
{
ans += tree[x];
x -= lowbit(x);
}
return ans;
}
int main()
{
scanf("%lld%lld%lld", &n, &m, &k);
for(ll i = 1; i <= n; i++)
scanf("%lld", &val[i]);
for(ll i = 1; i < n; i++)
{
ll u, v;
scanf("%lld%lld", &u, &v);
add(u, v);
add(v, u);
}
dfs(k, 0);
for(ll i = 1; i <= n; i++)
updata(l[i], val[i]);
while(m--)
{
ll op;
scanf("%lld", &op);
if(op == 1)
{
ll x, y;
scanf("%lld%lld", &x, &y);
updata(l[x], y);
}
else
{
ll x;
scanf("%lld", &x);
printf("%lld\n", query(r[x]) - query(l[x] - 1));
}
}
return 0;
}