標籤:
計算一個樹的子樹節點權值和,節點權值可以單個修改。
利用dfs序把一顆樹投影到數組裡,維護dfs序和子節點個數,然後用樹狀數組即可。
1 #include <cstdio> 2 #include <algorithm> 3 #include <cstring> 4 5 using namespace std; 6 7 const int maxn = 1e5+10; 8 int N,M,c[maxn],chdnum[maxn]; 9 int id_dfs[maxn],cnt_dfs; 10 bool vis[maxn]; 11 12 struct Edge{ 13 int to,next; 14 15 }edge[4*maxn]; 16 int head[maxn],tol; 17 18 int add_edge(int u,int v) 19 { 20 edge[tol].to = u; 21 edge[tol].next = head[v]; 22 head[v] = tol++; 23 24 edge[tol].to = v; 25 edge[tol].next = head[u]; 26 head[u] = tol++; 27 } 28 29 int dfs(int u) 30 { 31 int chd = 1; 32 vis[u] = true; 33 if(id_dfs[u] == -1) id_dfs[u] = cnt_dfs++; 34 35 for(int i = head[u];~i;i = edge[i].next) if(!vis[edge[i].to]) 36 { 37 int v = edge[i].to; 38 chd += dfs(v); 39 } 40 return chdnum[u] = chd; 41 } 42 43 int lowbit(int x) 44 { 45 return x & (-x); 46 } 47 48 void update(int x,int a) 49 { 50 while( x <= N) 51 { 52 c[x] += a; 53 x += lowbit(x); 54 } 55 } 56 57 int getsum(int x) 58 { 59 int res = 0; 60 while(x > 0) 61 { 62 res += c[x]; 63 x -= lowbit(x); 64 } 65 return res; 66 } 67 68 int query(int l,int r) 69 { 70 return getsum(r) - getsum(l-1); 71 } 72 73 int main() 74 { 75 while(~scanf("%d",&N)) 76 { 77 memset(head,-1,sizeof head); 78 memset(c,0,sizeof c); 79 memset(id_dfs,-1,sizeof id_dfs); 80 memset(vis,false,sizeof vis); 81 cnt_dfs = 1; 82 tol = 0; 83 84 for(int i=0,u,v;i<N-1;i++) 85 { 86 scanf("%d%d",&u,&v); 87 add_edge(u,v); 88 } 89 90 dfs(1); 91 92 for(int i=1;i<=N;i++) 93 { 94 //printf("i: dfs:%d\n",i,id_dfs[i]); 95 update(id_dfs[i],1); 96 } 97 scanf("%d",&M); 98 99 char op[5];100 int x;101 for(int i=0;i<M;i++)102 {103 scanf("%s%d",op,&x);104 //printf("sum:%d chnum:%d id:%d\n",query(id_dfs[x],id_dfs[x]),chdnum[x],id_dfs[x]);105 if(op[0] == ‘Q‘)106 {107 printf("%d\n",getsum(id_dfs[x]+chdnum[x]-1) - getsum(id_dfs[x]-1) );108 }109 else110 {111 if(query(id_dfs[x],id_dfs[x])) update(id_dfs[x],-1);112 else update(id_dfs[x],1);113 }114 }115 }116 }
POJ 3321-Apple Tree-樹狀數組+dfs序