poj 3321 dfs + 树状数组
2015-07-15 16:37
323 查看
题意:
给一棵树,然后每个叶子节点上开始的时候有一棵苹果,然后有如下操作:
C x , 如果 x 节点上有苹果,就摘下来,如果没有苹果,就长一个;
Q x,询问 x 这个父亲节点下共有几个苹果。
解析:
把树的深度遍历和树状数组组合的绝妙至极。
首先,考虑到怎么将一棵二维的树,拉成一维的到树状数组里面去维护个数。
dfs + 时间戳是一个非常妙的用法,刚好把s时间戳作为树状数组的左区间端点,e时间戳作为右区间端点。
这样处理就刚好把一个二维的树抽象成了一维,因为在当前这个父亲节点下的子节点的时间戳必然是在 (s,e)这个区间内的。
代码:
给一棵树,然后每个叶子节点上开始的时候有一棵苹果,然后有如下操作:
C x , 如果 x 节点上有苹果,就摘下来,如果没有苹果,就长一个;
Q x,询问 x 这个父亲节点下共有几个苹果。
解析:
把树的深度遍历和树状数组组合的绝妙至极。
首先,考虑到怎么将一棵二维的树,拉成一维的到树状数组里面去维护个数。
dfs + 时间戳是一个非常妙的用法,刚好把s时间戳作为树状数组的左区间端点,e时间戳作为右区间端点。
这样处理就刚好把一个二维的树抽象成了一维,因为在当前这个父亲节点下的子节点的时间戳必然是在 (s,e)这个区间内的。
代码:
#include <iostream> #include <cstdio> #include <cstdlib> #include <algorithm> #include <cstring> #include <cmath> #include <stack> #include <vector> #include <queue> #include <map> #include <climits> #include <cassert> #define LL long long #define lson lo, mi, rt << 1 #define rson mi + 1, hi, rt << 1 | 1 using namespace std; const int maxn = 100000 + 10; const int inf = 0x3f3f3f3f; const double eps = 1e-8; const double pi = acos(-1.0); const double ee = exp(1.0); int n; int c[maxn]; int lo[maxn], hi[maxn]; int mark[maxn]; int head[maxn]; int edgeNum; int dep; void init() { memset(c, 0, sizeof(c)); memset(head, -1, sizeof(head)); memset(lo, -1, sizeof(lo)); memset(hi, -1, sizeof(hi)); edgeNum = 0; dep = 0; } struct Tree { int to, next; } edge[maxn]; void addEdge(int fr, int to) { edge[edgeNum].to = to; edge[edgeNum].next = head[fr]; head[fr] = edgeNum++; } void dfs(int u) { lo[u] = ++dep;///debug for (int i = head[u]; i != -1; i = edge[i].next) { if (lo[edge[i].to] == -1) dfs(edge[i].to); } hi[u] = dep; } int lowbit(int x) { return x & -x; } void update(int x, int num) { while (x <= n) { c[x] += num; x += lowbit(x); } } int query(int x) { int res = 0; while (x) { res += c[x]; x -= lowbit(x); } return res; } int main() { #ifdef LOCAL freopen("in.txt", "r", stdin); #endif // LOCAL while (~scanf("%d", &n)) { init(); for (int i = 1; i <= n; i++) { mark[i] = 1; update(i, 1); } for (int i = 1; i < n; i++) { int fr, to; scanf("%d%d", &fr, &to); addEdge(fr, to); } dfs(1); // for (int i = 1; i <= n; i++) // cout << lo[i] << " " << hi[i] << endl; int m; scanf("%d", &m); while (m--) { char op[3]; scanf("%s", op); int rt; scanf("%d", &rt); if (op[0] == 'Q') { printf("%d\n", query(hi[rt]) - query(lo[rt] - 1)); } if (op[0] == 'C') { if (mark[rt]) { update(lo[rt], -1); mark[rt] = 0; } else { update(lo[rt], 1); mark[rt] = 1; } } } } return 0; }
相关文章推荐
- YT05-动态归划求解课后题目-1001—FatMouse's Speed-(6.21日-烟台大学ACM预备队解题报告)
- secureCRT使用VIM时对语法高亮
- Hive不同文件的读取与序列化
- 前端性能优化和规范
- PHP用星号隐藏部份用户名、身份证、IP、手机号、邮箱等实例
- eclipse 恢复已删除的文件和代码
- c语言详解sizeof
- Ride
- JavaWeb学习总结(五十)——文件上传和下载
- postgresql-9.3的增量备份
- mono-3.4.0 源码安装时出现的问题 [do-install] Error 2 [install-pcl-targets] Error 1 解决方法
- C++ 线程池,任务池实现实例
- maven打一个可执行的jar包
- Easyui 二级菜单
- 博友话题:运维工程师必须掌握哪些基础技能?
- Communications Link failure
- 苹果iPhone连接wifi就进去www.apple.com主页 下边显示 <HTML><HEAD><TITLE>Success</TITLE></HEAD><BODY>Success</BODY>
- 不同版本iOS的特性和差异
- String的深入了解
- codeforces 339E Three Swaps (搜索 dfs)