线段树 poj3321 Apple Tree
2015-08-09 20:36
218 查看
真没想到,,原来树型结构只要稍微处理一下,竟然可以变成赤裸裸的线性结构,然后用线段树去处理!
对于这道题,一开始很难想清楚,如何将树型结构转换
线段树的前提是连续的区间,那能不能将树型结构变成线性结构呢?
我们从根节点按照前序遍历给节点依次编号,对于每个节点,当访问完子树之后,将子树的最大节点也保存,那么这样就能得到一个区间段,见下图:
然后会惊奇的发现,,当我们要查询某个节点的子树中的操作时,只要访问对应的连续区间就可以了!
我们就这样将树型结构转换成了线性结构,,就可以各种套用线段树和树状数组了~
对于这道题,一开始很难想清楚,如何将树型结构转换
线段树的前提是连续的区间,那能不能将树型结构变成线性结构呢?
我们从根节点按照前序遍历给节点依次编号,对于每个节点,当访问完子树之后,将子树的最大节点也保存,那么这样就能得到一个区间段,见下图:
然后会惊奇的发现,,当我们要查询某个节点的子树中的操作时,只要访问对应的连续区间就可以了!
我们就这样将树型结构转换成了线性结构,,就可以各种套用线段树和树状数组了~
#include<map> #include<set> #include<cmath> #include<queue> #include<cstdio> #include<string> #include<vector> #include<cstring> #include<iostream> #include<algorithm> #include<functional> using namespace std; typedef long long LL; typedef pair<LL, int> PLI; const int MX = 2e5 + 5; const int INF = 0x3f3f3f3f; #define lson l,m,rt<<1 #define rson m+1,r,rt<<1|1 #define root 1,n,1 #define RR rt<<1|1 #define LL rt<<1 int S[MX << 2]; int Beg[MX], End[MX], clock; int Head[MX], Next[MX], rear; struct Edge { int u, v; } E[MX]; void edge_init() { rear = 0; memset(Head, -1, sizeof(Head)); } void edge_add(int u, int v) { E[rear].u = u; E[rear].v = v; Next[rear] = Head[u]; Head[u] = rear++; } int DFS(int u, int from) { Beg[u] = ++clock; int last = Beg[u]; for(int i = Head[u]; ~i; i = Next[i]) { int v = E[i].v; if(v == from) continue; last = DFS(v, u); } return End[u] = last; } void push_up(int rt) { S[rt] = S[LL] + S[RR]; } void build(int l, int r, int rt) { if(l == r) { S[rt] = 1; return; } int m = (l + r) >> 1; build(lson); build(rson); push_up(rt); } void update(int x, int l, int r, int rt) { if(l == r) { S[rt] ^= 1; return; } int m = (l + r) >> 1; if(x <= m) update(x, lson); else update(x, rson); push_up(rt); } int query(int L, int R, int l, int r, int rt) { if(L <= l && r <= R) { return S[rt]; } int m = (l + r) >> 1, ret = 0; if(L <= m) ret += query(L, R, lson); if(R > m) ret += query(L, R, rson); return ret; } int main() { int n, Q; //freopen("input.txt", "r", stdin); while(~scanf("%d", &n)) { clock = 0; edge_init(); for(int i = 1; i <= n - 1; i++) { int u, v; scanf("%d%d", &u, &v); edge_add(u, v); edge_add(v, u); } DFS(1, -1); build(root); scanf("%d", &Q); while(Q--) { char op[5]; int x; scanf("%s%d", op, &x); if(op[0] == 'Q') { printf("%d\n", query(Beg[x], End[x], root)); } else update(Beg[x], root); } } return 0; }
相关文章推荐
- 关于Android数据存储方式(一)——SharedPreferences
- Android基础知识----01
- Android:实现EditText在获得焦点后消去hint,失去焦点后再显示原来的hint
- android分辨率 尺寸 dpi换算
- Android兼容性测试框架(CTS)手册
- Android基础之px,dp,sp对比以及应用
- unity界面学习01
- Android TextView属性大全
- Android编译系统环境初始化过程分析
- Android OOM异常解决方案
- Scut游戏server引擎Unity3d访问
- Android ANR异常解决方案
- Android源代码编译命令m/mm/mmm/make分析
- iOS开发--改变tableHeaderView的高度
- ios 修改程序显示名称
- android 取消标题 程序意外停解决方法
- Android-Universal-Image-Loader三大组件DisplayImageOptions、ImageLoader、ImageLoaderConfiguration详解
- Objective-C学习笔记_字面量
- iOS开发-- 字符串分割、拼接
- android图片的异步加载和双缓存学习笔记——DisplayImageOptions