ZOJ 3686 A Simple Tree Problem(将对树的操作转化成区间=>线段树)
来源:互联网 发布:淘宝电商学院哪个好 编辑:程序博客网 时间:2024/06/05 15:16
题目链接:Click here~~
题意:
给一颗确定的树,每个节点只有 0 和 1 两种状态。
两种操作:1、将某颗子树的0变1,1变0。
2、询问某颗子树的1的个数。
解题思路:
一看这两种操作,很容易就联想到了线段树,但问题是,区间在哪里???
由于操作都是对一颗树进行的,我们要想办法把它和区间联系起来。
不妨把 每个节点都看做一个数,每棵树都看做一个区间。
因为一共有 n 个点,我们把树根看做1,区间看做 [1,n]。
树根的孩子看做多少呢?2、3、4、5、6?
显然是不可以的,因为这样对 “2” 这颗树操作的时候,"2" 的子树不再是一段区间。
所以,3 应该让 "2" 的孩子来当。
…… 依次类推,怎么样,很像递归吧?
如果没懂的话,画个图仔细想想吧。
做法嘛,dfs 一下就好了。
转化成区间之后,就是很简单的 线段树 问题了。
#include <vector>#include <stdio.h>#include <string.h>#include <algorithm>using namespace std;#define lson u<<1#define rson u<<1|1const int N = 1e5+3;vector<int> g[N];struct Int{ int a,b;}I[N];int id;void dfs(int u){ I[u].a = ++id; for(int i=0;i<(int)g[u].size();i++) dfs(g[u][i]); I[u].b = id;}struct SegTree{ int l,r,sum,lazy; inline int mid() { return l+r >> 1; } inline int len() { return r-l; }}T[N<<2];void push_down(int u){ if(!T[u].lazy) return ; T[lson].sum = T[lson].len() - T[lson].sum; T[rson].sum = T[rson].len() - T[rson].sum; T[lson].lazy ^= 1; T[rson].lazy ^= 1; T[u].lazy = 0;}void push_up(int u){ T[u].sum = T[lson].sum + T[rson].sum;}void build(int u,int l,int r){ T[u].l = l , T[u].r = r; T[u].sum = T[u].lazy = 0; if(l == r-1) { return ; } int m = T[u].mid(); build(lson,l,m); build(rson,m,r);}void updata(int u,int l,int r){ if(l == T[u].l && r == T[u].r) { T[u].sum = T[u].len() - T[u].sum; T[u].lazy ^= 1; return ; } push_down(u); int m = T[u].mid(); if(r <= m) updata(lson,l,r); else if(l >= m) updata(rson,l,r); else { updata(lson,l,m); updata(rson,m,r); } push_up(u);}int query(int u,int l,int r){ if(l == T[u].l && r == T[u].r) return T[u].sum; push_down(u); int m = T[u].mid(); if(r <= m) return query(lson,l,r); else if(l >= m) return query(rson,l,r); else return query(lson,l,m) + query(rson,m,r);}int main(){ int n,Q,u; char cmd[5]; while(~scanf("%d%d",&n,&Q)) { for(int i=1;i<=n;i++) g[i].clear(); for(int i=2;i<=n;i++) { int num; scanf("%d",&num); g[num].push_back(i); } id = 0; dfs(1); build(1,1,n+1); while(Q--) { scanf("%s%d",cmd,&u); if(cmd[0] == 'o') updata(1,I[u].a,I[u].b+1); else printf("%d\n",query(1,I[u].a,I[u].b+1)); } puts(""); } return 0;}
- ZOJ 3686 A Simple Tree Problem(将对树的操作转化成区间=>线段树)
- ZOJ 3686 A Simple Tree Problem(树转线段树+线段树区间更新)
- ZOJ 3686 A Simple Tree Problem DFS+线段树(区间取反)
- zoj 3686 A Simple Tree Problem(dfs+线段树)
- ZOJ 3686-A Simple Tree Problem (DFS+线段树)
- ZOJ 3686 A Simple Tree Problem (线段树)
- ZOJ 3686 A Simple Tree Problem (线段树)
- ZOJ 3686 A Simple Tree Problem(线段树)
- ZOJ Monthly, March 2013 A题 A Simple Tree Problem(线段树)#zh
- BNUOJ 28887 A Simple Tree Problem(线段树, 区间查询,区间更新)
- A Simple Problem with Integers(线段树,区间求和)
- A Simple Problem with Integers (线段树区间更新)
- BNU A Simple Tree Problem 线段树
- ZOJ3696-A Simple Tree Problem 线段树
- [DFS序列+线段树维护区间标记]ZOJ3686 A Simple Tree Problem
- ZOJ 3686 A A Simple Tree Problem
- A Simple Problem with Integers(线段树之区间点的成段更新)
- poj 3468 A Simple Problem with Integers(线段树的区间更新与求和)
- [3月27日的脚本] 修复Event ID 4107 and Event ID 11 问题(VBScript)
- .net 前台显示日期格式化代码
- 不重复地输出升序数组中的元素
- JSON数据类型
- 一年了,乱七八糟地一点点心得。
- ZOJ 3686 A Simple Tree Problem(将对树的操作转化成区间=>线段树)
- activiti5学习资料(bpmn2.0新规范)
- 一天一linux命令(4) man 在线帮助系统
- 产品经理,你用多少时间来思考
- 真正是实现登陆与主窗体的交互,进程关闭!!!
- Linux下pppoe设置
- ASIHTTPRequest with Https
- [3月28日的脚本] 修复Event ID 4107 and Event ID 11 问题 (PowerShell)
- 开始学php