POJ 3321 Apple Tree (树状数组)
2015-10-19 16:20
295 查看
题目:http://poj.org/problem?id=3321
题意:给出一颗树,一开始树是满的(每个结点都有苹果)两种操作;1)C x ,x结点有苹果则摘掉这个苹果,否则加上一个苹果;2)Q x ,询问结点x为根的子树上共有多少苹果(包括x上的苹果)
思路:
关键是把这颗树转化为树状数组,一颗子树中的结点要占连续的空间,访问时才方便方法是dfs给各个结点编号。
每个结点对应两个编号:以这个结点为跟的子树所占的连续空间的开始位置s和结束位置e。
树状数组bit[ i ]记录从开头到 i 这一段的和,那么所求就是bit[ e ] - bit[ s ]。
才知道POJ用stl会很慢啊(大概是指针操作的问题吧),要用数组保存边信息建树,用vector会T。
题意:给出一颗树,一开始树是满的(每个结点都有苹果)两种操作;1)C x ,x结点有苹果则摘掉这个苹果,否则加上一个苹果;2)Q x ,询问结点x为根的子树上共有多少苹果(包括x上的苹果)
思路:
关键是把这颗树转化为树状数组,一颗子树中的结点要占连续的空间,访问时才方便方法是dfs给各个结点编号。
每个结点对应两个编号:以这个结点为跟的子树所占的连续空间的开始位置s和结束位置e。
树状数组bit[ i ]记录从开头到 i 这一段的和,那么所求就是bit[ e ] - bit[ s ]。
才知道POJ用stl会很慢啊(大概是指针操作的问题吧),要用数组保存边信息建树,用vector会T。
#include <stdio.h> #include <string.h> #include <algorithm> #include <math.h> #include <stdlib.h> #define INF 0x7fffffff #define MOD 1000000007 #include <vector> using namespace std; typedef long long ll; const int MAXN = 100005; vector<int> G[MAXN]; int n, m; int s[MAXN], e[MAXN], cnt, apple[MAXN], bit[2 * MAXN]; struct Edge { int to, next; }edge[2 * MAXN]; int f[MAXN]; void addedge(int u, int v) { edge[cnt].to = v; edge[cnt].next = f[u]; f[u] = cnt++; } void dfs(int u) { s[u] = cnt++; for(int i = f[u]; i != -1; i = edge[i].next) { if(!s[edge[i].to]) dfs(edge[i].to); } e[u] = cnt++; } void update(int i, int x) { //printf("update %d\n", i); while(i <= 2 * n) { bit[i] += x; i += i & -i; } } int sum(int i) { int s = 0; while(i > 0) { s += bit[i]; i -= i & -i; } return s; } int main() { #ifdef LOCAL freopen("data.in", "r", stdin); #endif int u, v, x; char c; while(scanf("%d", &n) != EOF) { for(int i = 0; i <= n; i++) G[i].clear(); memset(bit, 0, sizeof(bit)); memset(s, 0, sizeof(s)); memset(e, 0, sizeof(e)); memset(apple, 0, sizeof(apple)); memset(f, -1, sizeof(f)); cnt = 0; for(int i = 0; i < n - 1; i++) { scanf("%d%d", &u, &v); //G[u].push_back(v); G[v].push_back(u); addedge(u, v); addedge(v, u); } cnt = 1; dfs(1); for(int i = 1; i <= n; i++) { //printf("%d:%d-%d\n", i, s[i], e[i]); update(e[i], 1); apple[i] = 1; } scanf("%d", &m); for(int i = 0; i < m; i++) { scanf(" %c%d", &c, &x); //printf("%c %d\n", c, x); if(c == 'Q') { printf("%d\n", sum(e[x]) - sum(s[x])); } else { if(apple[x]) { update(e[x], -1); apple[x] = 0; } else { update(e[x], 1); apple[x] = 1; } } } } return 0; }
相关文章推荐
- Android中的Shape使用总结
- Hibernate之mappedBy
- Android如何使用命令行查看数据库SQLite3
- Object.create()兼容实现方法
- IDA动态调试Android的DEX文件
- Android开发总结笔记 四大组件之BroadcastReceiver 1-2-7
- android蛋疼的OOM
- android 串口调试
- Android支付宝集成
- AndroidStudio的一些坑
- iOS开发日记35-事件处理机制与图像渲染过程
- iOS经典讲解之清除缓存文件
- WAYS TO UPDATE YOUR DEVICE
- ios app 内存泄露分析
- Android init.rc文件解析过程详解(一)
- android应用框架系列二,图形界面
- AndroidStudio提交代码到Github(详细图文)
- android studio 在release打包时修改AndroidManifest.xml
- Swift UITableView相关功能(六)头视图的高度
- Android按返回键退出程序但不销毁,程序后台运行,同QQ退出处理方式