求和 --dfs序+树状数组
标签:依次 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 2 #include
3 #includestring.h>
4 #includestring>
5 #include 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;i2*M;i++)
19 edge[i].nxt=-1;
20 for(int i=1;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(xn){
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"%d",&a[i]);
59 for(int i=1;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){
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 }
View Code
求和 --dfs序+树状数组
标签:依次 one span bit https void const sum hide
原文地址:https://www.cnblogs.com/AndreaHtj/p/13761731.html
评论