POJ-3321 Apple Tree---树状数组+DFS序
题目链接:
https://vjudge.net/problem/POJ-3321
题目大意:
题目大意级是说,给你一颗树,最初每个节点上都有一个苹果,有两种操作:修改(即修改某一个节点,修改时这一个节点苹果从有到无,或从无到有)和查询(查询某一个节点他的子树上有多少个苹果)。
解题思路:
对树的每个节点进行编号,按照先序遍历进行编号,这样可以处理出一段区间,使得区间内都是点i的子树,求和的时候只要求区间和即可。
黑色是原来的编号,蓝色为用先序遍历得到的编号
超级坑的一点:
这里用vector<int>G[maxn]会超时
用vector<vector<int> > G(maxn)就过了
1 #include<cstdio> 2 #include<cstring> 3 #include<iostream> 4 #include<algorithm> 5 #include<string> 6 #include<cmath> 7 #include<set> 8 #include<queue> 9 #include<map> 10 #include<stack> 11 #include<vector> 12 #include<list> 13 #include<deque> 14 #include<sstream> 15 #include<cctype> 16 #define REP(i, n) for(int i = 0; i < (n); i++) 17 #define FOR(i, s, t) for(int i = (s); i < (t); i++) 18 #define MEM(a, x) memset(a, x, sizeof(a)); 19 using namespace std; 20 typedef long long ll; 21 typedef unsigned long long ull; 22 const int maxn = 1e5 + 10; 23 const double eps = 1e-10; 24 const int INF = 1 << 30; 25 const int dir[4][2] = {1,0,0,1,0,-1,-1,0}; 26 const double pi = 3.1415926535898; 27 int T, n, m, cases, tot; 28 int tree[maxn], lef[maxn], rig[maxn], s[maxn];///s数组记录该节点是否有树 29 vector<vector<int> >a(maxn); 30 void dfs(int x) 31 ///dfs给树节点编号,分别编成左节点和右节点, 32 ///左节点就是本身,右节点是可到达的节点的最大编号, 33 ///之后查询节点x的子树就可以直接查询[le[x], rig[x]]的区间和 34 { 35 lef[x] = tot; 36 for(int i = 0; i < a[x].size(); i++) 37 { 38 tot++; 39 dfs(a[x][i]); 40 } 41 rig[x] = tot; 42 } 43 int lowbit(int x) 44 { 45 return x&(-x); 46 } 47 int sum(int x) 48 { 49 int ret = 0; 50 while(x > 0) 51 { 52 ret += tree[x]; 53 x -= lowbit(x); 54 } 55 return ret; 56 } 57 int add(int x, int d) 58 { 59 while(x <= n) 60 { 61 tree[x] += d; 62 x += lowbit(x); 63 } 64 } 65 int main() 66 { 67 int x, y; 68 char c[5]; 69 while(scanf("%d", &n) != EOF) 70 { 71 MEM(lef, 0); 72 MEM(rig, 0); 73 MEM(s, 0); 74 MEM(tree, 0); 75 for(int i = 0; i < maxn; i++)a[i].clear(); 76 for(int i = 1; i < n; i++) 77 { 78 scanf("%d%d", &x, &y); 79 a[x].push_back(y); 80 } 81 tot = 1; 82 dfs(1); 83 for(int i = 1; i <= n; i++) 84 { 85 s[i] = 1; 86 add(i, 1); 87 } 88 scanf("%d", &m); 89 while(m--) 90 { 91 scanf("%s%d", c, &x); 92 if(c[0] == 'Q') 93 { 94 cout << sum(rig[x]) - sum(lef[x] - 1) << endl; 95 } 96 else if(c[0] == 'C') 97 { 98 if(s[x])add(lef[x], -1); 99 else add(lef[x], 1); 100 s[x] = !s[x];///更新该点是否有苹果 101 } 102 } 103 } 104 return 0; 105 }
越努力,越幸运