ZOJ 3686 A Simple Tree Problem(将对树的操作转化成区间=>线段树)
2013-04-01 14:33
323 查看
题目链接: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 一下就好了。
转化成区间之后,就是很简单的 线段树 问题了。
题意:
给一颗确定的树,每个节点只有 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|1 const int N = 1e5+3; vector<int> g ; struct Int { int a,b; }I ; 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(树转线段树+线段树区间更新)
- BNU 28887——A Simple Tree Problem——————【将多子树转化成线段树+区间更新】
- 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 3686 A Simple Tree Problem (线段树)
- ZOJ-3686 A Simple Tree Problem 线段树
- ZOJ 3686 A Simple Tree Problem(线段树)
- zoj 3686 A Simple Tree Problem (线段树)
- zoj 3686 A Simple Tree Problem
- ZOJ_3686_A Simple Tree Problem(线段树成端更新)
- POJ 3468 A Simple Problem with Integers(线段树|区间加减&&区间求和)
- ZOJ3686 A Simple Tree Problem
- zoj3686 A Simple Tree Problem
- poj 3468 A Simple Problem with Integers(线段树,区间更新&求和)
- zoj 3686 A Simple Tree Problem
- ZOJ 3686 A A Simple Tree Problem
- ZOJ 3686 A Simple Tree Problem
- ZOJ 3686 A Simple Tree Problem