#144. DFS 序 1
好久没做 序了,复习一波。
序说白了就是对一棵树进行 时结点被遍历的顺序。
序的性质:对于一棵子树的遍历顺序一定是连续的。
因此我们可以记录开始进入以 为根的子树的顺序 ,和遍历 的最后一个叶子结点的顺序 。这里我们就可以实现对一棵树进行区间操作了。
这里的题目是单点更新,区间查询,显然 序转树状数组就是板子题。
#include<bits/stdc++.h>
using namespace std;
typedef long long ll;
const int N=1e6+5,M=2e4+5,inf=0x3f3f3f3f,mod=1e9+7;
#define mst(a) memset(a,0,sizeof a)
#define lx x<<1
#define rx x<<1|1
#define reg register
#define PII pair<int,int>
#define fi first
#define se second
#define pb push_back
#define lowbit(x) x&(-x)
#define il inline
template<class T>
inline void read(T &x){
x=0;int w=1;
char ch=getchar();
while(ch<'0'||ch>'9') {if(ch=='-') w=-1;ch=getchar();}
for(;ch>='0'&&ch<='9';ch=getchar())
x=(x<<3)+(x<<1)+(ch&15);
x*=w;
}
ll a[N],tr[N];
int in[N],out[N],h[N];
int tot,n,m,cnt,st;
struct edge{
int to,nt;
}e[N<<1];
il void add(int u,int v){
e[++cnt]={v,h[u]},h[u]=cnt;
}
void upd(int x,int k){ //单点更新.
while(x<=n){
tr[x]+=k;
x+=lowbit(x);
}
}
ll query(int x){ //求和.
ll ans=0;
while(x){
ans+=tr[x];
x-=lowbit(x);
}
return ans;
}
void dfs(int u,int fa){ //求出dfx序,构造树状数组.
in[u]=++tot,upd(in[u],a[u]);
for(int i=h[u];i;i=e[i].nt){
if(e[i].to==fa) continue;
dfs(e[i].to,u);
}
out[u]=tot;//out[u]表示以u为根的子树的最后一个结点编号,类似于区间的右端点.
}
int main(){
read(n),read(m),read(st);
for(reg int i=1;i<=n;i++) read(a[i]);
for(reg int i=1,u,v;i<n;i++)
read(u),read(v),add(u,v),add(v,u);
dfs(st,0);
while(m--){
int op,a,x;
read(op),read(a);
if(op==1) read(x),upd(in[a],x);
else printf("%lld\n",query(out[a])-query(in[a]-1));
}
return 0;
}