標籤:
多次修改一棵樹節點的值,或者詢問當前這個節點的子樹所有節點權值總和。
首先預先處理出DFS序L[i]和R[i]
把問題轉化為區間查詢總和問題。單點修改,區間查詢,樹狀數組即可。
注意修改的時候也要按照dfs序修改,因為你查詢就是按照dfs查的,所以修改也要用dfs序修改
L[i]是唯一的。
#include <cstdio>#include <cstdlib>#include <cstring>#include <cmath>#include <algorithm>using namespace std;#define inf (0x3f3f3f3f)typedef long long int LL;#include <iostream>#include <sstream>#include <vector>#include <set>#include <map>#include <queue>#include <string>const int maxn = 100000 + 20;int first[maxn], L[maxn], R[maxn], a[maxn];struct edge { int u, v; int next;} e[maxn * 2];int n, num;void add (int u, int v){ ++num; e[num].u = u; e[num].v = v; e[num].next = first[u]; first[u] = num;}bool book[maxn];int index;void dfs (int cur){ L[cur] = index; for (int i = first[cur]; i; i = e[i].next) { if (book[e[i].v] == 0) { book[e[i].v] = 1; index++; dfs (e[i].v); } } R[cur] = index;}int c[maxn];//樹狀數組,多case的記得要清空int lowbit (int x)//得到x二進位末尾0的個數的2次方 2^num{ return x&(-x);}void addc (int pos,int val)//在第pos位加上val這個值{ while (pos<=n) { //n是元素的個數 c[pos] += val; pos += lowbit(pos); } return ;}int get_sum (int pos) //求解:1--pos的總和{ int ans = 0; while (pos) { ans += c[pos]; pos -= lowbit(pos); } return ans;}void work (){ for (int i = 1; i <= n - 1; ++i) { int u, v; scanf ("%d%d", &u, &v); add (u, v); } for (int i = 1; i <= n; ++i) { addc (i, 1); a[i] = 1; } dfs (1); int m; scanf ("%d", &m); for (int i = 1; i <= m; ++i) { char str[3]; int id; scanf ("%s%d", str, &id); if (str[0] == ‘Q‘) { printf ("%d\n", get_sum (R[id]) - get_sum (L[id] - 1)); } else { id = L[id]; //查詢用dfs序查,那麼更改也要用dfs序更改 a[id] = -a[id]; addc (id, a[id]); } } return ;}int main (){#ifdef local freopen("data.txt","r",stdin);#endif while (~scanf ("%d", &n)) { index = 1; work (); memset (first, 0, sizeof first); num = 0; memset (book, 0, sizeof book); memset (c, 0, sizeof c); } return 0;}View Code
POJ 3321 Apple Tree DFS序 + 樹狀數組