POJ 3321 Apple Tree
题目链接:【http://poj.org/problem?id=3321】
题意:给你一棵树,有两种操作,第一种是对某个节点进行修改(该节点如果有苹果,就拿掉,如果没有苹果就放上去一个),第二种操作是询问以节点x为根的子树上有多少苹果。
题解:对一棵树进行DFS,对每一个节点重新编号,并记录下某个节点出的时候当前结点的最大值,也就是说记录了每个节点的编号和这个节点为根所表示的最大区间。这样就可以对利用单点修改区间求和进行求解。
#include<cstdio> #include<cstring> #include<algorithm> using namespace std; const int maxn = 1e6 + 15; int N, M; struct Edge { int to, next; Edge (int to = 0, int next = 0): to(to), next(next) {} } E[maxn]; int head[maxn], tot; void initEdge() { memset(head, -1, sizeof(head)); tot = 0; } void addEdge(int u, int v) { E[tot] = Edge(v, head[u]); head[u] = tot++; } int L[maxn], R[maxn], dfs_clock; void DFS(int u, int fa) { L[u] = ++dfs_clock; for(int k = head[u]; ~k; k = E[k].next) { int v = E[k].to; if(v == fa) continue; DFS(v, u); } R[u] = dfs_clock; } int sum[maxn], vis[maxn]; int low_bit(int x) { return x & (-x); } void add_Sum(int p, int val) { while(p <= N) { sum[p] += val; p += low_bit(p); } } int get_Sum(int p) { int ret = 0; while(p) { ret += sum[p]; p -= low_bit(p); } return ret; } int main () { initEdge(); scanf("%d", &N); for(int i = 1; i <= N - 1; i++) { int u, v; scanf("%d %d", &u, &v); addEdge(u, v); addEdge(v, u); } DFS(1, 0); for(int i = 1; i <= N; i++) { add_Sum(i, 1); vis[i] = 1; } scanf("%d", &M); for(int i = 1; i <= M; i++) { char s[5]; int p; scanf("%s %d", s + 1, &p); if(s[1] == 'C') { if(vis[L[p]]) add_Sum(L[p], -1); else add_Sum(L[p], 1); vis[L[p]] ^= 1; } else if(s[1] == 'Q') { int t1 = get_Sum(R[p]); int t2 = get_Sum(L[p] - 1); printf("%d\n", t1 - t2); } } return 0; }
想的太多,做的太少。