标签:依次 one span bit https void const sum hide
题意:
链接:https://ac.nowcoder.com/acm/contest/5158/I
思路:树状数组主要针对的是区间(而且是一条线段的)求和问题,所以需要利用dfs序和数组 in [ ], out [ ] (前缀和原理),利用dfs进行搜索,每个点依次被访问的顺序就是每个点的dfs序,out [ i ] - in [ i ] 即为子树 i 的区间,
这样就将一棵树记录到了树状数组上。
代码:
链式前向星+dfs序+树状数组
1 #include<stdio.h> 2 #include<algorithm> 3 #include<string.h> 4 #include<string> 5 #include<iostream> 6 using namespace std; 7 typedef long long ll; 8 #define lowbit(x) (x&(-x)) 9 const int M=1000010; 10 struct node{ 11 int to,nxt; 12 }; 13 node edge[M*2]; 14 int a[M],cnt,tag,n,head[M],in[M],out[M]; 15 ll tree[M]; 16 void init(){ 17 memset(tree,0,sizeof(tree)); 18 for(int i=1;i<2*M;i++) 19 edge[i].nxt=-1; 20 for(int i=1;i<M;i++) 21 head[i]=-1; 22 cnt=0; 23 } 24 void add(int v,int u){ 25 cnt++; 26 edge[cnt].to=v; 27 edge[cnt].nxt=head[u]; 28 head[u]=cnt; 29 } 30 void add1(int x,int d){ 31 while(x<=n){ 32 tree[x]+=d; 33 x+=lowbit(x); 34 } 35 } 36 ll sum(int x){ 37 ll ans=0; 38 while(x){ 39 ans+=tree[x]; 40 x-=lowbit(x); 41 } 42 return ans; 43 } 44 void dfs(int x,int fa){ 45 in[x]=++tag; 46 add1(tag,a[x]); 47 for(int i=head[x];i!=-1;i=edge[i].nxt){ 48 int tem=edge[i].to; 49 if(tem!=fa)dfs(tem,x); 50 } 51 out[x]=tag; 52 } 53 int main(){ 54 int m,k,u,v,p; 55 while(~scanf("%d%d%d",&n,&m,&k)){ 56 tag=0; 57 init(); 58 for(int i=1;i<=n;i++)scanf("%d",&a[i]); 59 for(int i=1;i<n;i++){ 60 scanf("%d%d",&u,&v); 61 add(u,v); 62 add(v,u); 63 } 64 dfs(k,0); 65 for(int i=1;i<=m;i++){ 66 scanf("%d",&p); 67 if(p==1){ 68 scanf("%d%d",&u,&v); 69 add1(in[u],v); 70 } 71 else{ 72 scanf("%d",&v); 73 printf("%lld\n",sum(out[v])-sum(in[v]-1)); 74 } 75 } 76 } 77 return 0; 78 }
标签:依次 one span bit https void const sum hide
原文地址:https://www.cnblogs.com/AndreaHtj/p/13761731.html