【DFS序+线段树】#145. DFS 序 2
这道题目和DFS1基本一致,修改的为区间,所以使用线段树
代码
#include<bits/stdc++.h> using namespace std; const int maxn=1e6+5; int n,m,root,cnt,times; int v[maxn],le[maxn],ri[maxn],num[maxn],head[maxn]; struct edge { int to,nxt; }e[maxn<<2]; void add(int x,int y) { e[++cnt].to=y; e[cnt].nxt=head[x]; head[x]=cnt; } struct point { int l,r; long long val,lz; }tr[maxn<<2]; void dfs(int u,int fa) { le[u]=++times; num[times]=u; for(int i=head[u];i;i=e[i].nxt) { int to=e[i].to; if(to==fa) continue; dfs(to,u); } ri[u]=times; } void pushup(int now) { tr[now].val=tr[now<<1].val+tr[now<<1|1].val; } void build(int now,int l,int r) { tr[now].l=l; tr[now].r=r; if(l==r) { tr[now].val=v[num[l]]; return; } int mid=(l+r)>>1; build(now<<1,l,mid); build(now<<1|1,mid+1,r); pushup(now); } void pushdown(int now) { if(!tr[now].lz) return; tr[now<<1].lz+=tr[now].lz; tr[now<<1|1].lz+=tr[now].lz; tr[now<<1].val+=1LL*(tr[now<<1].r-tr[now<<1].l+1)*tr[now].lz; tr[now<<1|1].val+=1LL*(tr[now<<1|1].r-tr[now<<1|1].l+1)*tr[now].lz; tr[now].lz=0; return; } void update(int now,int l,int r,int val) { if(tr[now].l>=l && tr[now].r<=r) { tr[now].val+=1LL*val*(tr[now].r-tr[now].l+1); tr[now].lz+=val; return; } pushdown(now); int mid=(tr[now].l+tr[now].r)>>1; if(l<=mid) update(now<<1,l,r,val); if(r>mid) update(now<<1|1,l,r,val); pushup(now); } long long query(int now,int l,int r) { if(tr[now].l>=l && tr[now].r<=r) return tr[now].val; int mid=(tr[now].l+tr[now].r)>>1; pushdown(now); long long res=0; if(l<=mid) res+=query(now<<1,l,r); if(r>mid) res+=query(now<<1|1,l,r); return res; } int main() { freopen("a.in","r",stdin); freopen("a.out","w",stdout); scanf("%d%d%d",&n,&m,&root); for(int i=1;i<=n;i++) scanf("%d",&v[i]); int x,y; for(int i=1;i<n;i++) { scanf("%d%d",&x,&y); add(x,y); add(y,x); } dfs(root,0); build(1,1,n); for(int i=1;i<=m;i++) { int op; scanf("%d",&op); if(op==1) { scanf("%d%d",&x,&y); update(1,le[x],ri[x],y); } else { scanf("%d",&x); printf("%lld\n",query(1,le[x],ri[x])); } } return 0; }