zoj 3686 (a simple tree problem)
来源:互联网 发布:ubuntu 循环登录 编辑:程序博客网 时间:2024/05/22 02:03
题目链接:点击打开链接
题目大意:给一棵树,节点上只有0 1,初始为0,进行operate则将此节点为根节点的子树都变为与之相反的。询问某个节点的子树1的个数。
题目分析:一看就是线段数,但是区间怎么找?所以要经过处理。参考了大神的想法http://blog.csdn.net/lenleaves/article/details/8759598。
我们要先用dfs将这个树遍历,之后形成一个线性序列。
比如
1
2 3 4
5 6 7 8 9
比如这棵树 dfs遍历之后的序列 是
1 2 5 6 3 4 7 8 9
我们可以看到每一颗子树的节点都在一个区间上。利用这个就可以写成成段更新的线段树了。
网上说的先序遍历或者是记录时间簇都是一个意思,要对某个节点的子树进行操作时 就是对它左边的一个区间操作,所以下面我们可以大刀阔斧的进行线段数操作。题目总结:还是自己太菜了,加油吧~~阿歇!
学习前向星写法点击打开链接,malash的大牛:点击打开链接
#include<cstdio>#include<cstring>#include<stack>#include<iostream>#include<algorithm>#define maxn 100005using namespace std;struct nodes{ int u,v;} edge[maxn];int head[maxn],e,p,node[maxn<<2],con[maxn<<2];//node记录有多少个1;con[]用于更新int l[maxn],r[maxn];char q[2];void add(int u,int v){ edge[e].u=v;//u:Parent;v:child edge[e].v=head[u]; head[u]=e++;}void dfs(int u){ l[u]=++p; for(int i=head[u]; i!=-1; i=edge[i].v) dfs(edge[i].u); r[u]=p;}void push_up(int rt){ node[rt]= node[rt<<1]+node[rt<<1|1];}void push_down(int rt,int m){ if(con[rt]) { con[rt<<1]^=1; con[rt<<1|1]^=1; node[rt<<1]=(m-(m>>1))-node[rt<<1];//延迟向下的更新 node[rt<<1|1]=(m>>1)-node[rt<<1|1]; con[rt]=0; }}void build(int l, int r, int rt){ con[rt]=0; if(l==r) { node[rt]=0; return ; } int m=(r+l)>>1; build(l,m,rt<<1);build(m+1,r,rt<<1|1); push_up(rt);}void update(int L,int R,int l,int r,int rt){ int m; if(l>=L&&R>=r) { con[rt]^=1; node[rt]=(r-l+1)-node[rt]; return; } m=(l+r)>>1; push_down(rt,r-l+1); if(L<=m) update(L,R,l,m,rt<<1); if(R>m) update(L,R,m+1,r,rt<<1|1); push_up(rt);}int query(int L,int R,int l,int r,int rt){ if(L<=l&&r<=R) { return node[rt]; } int ans=0,m=(r+l)>>1; push_down(rt,r-l+1); if(L<=m) ans+=query(L,R,l,m,rt<<1); if(R>m) ans+=query(L,R,m+1,r,rt<<1|1); return ans;}int main(){ int n,m,i,j,t; while(~scanf("%d%d",&n,&m)) { build(1,n,1); memset(head,-1,sizeof(head)),e=0,p=0; for(i=2; i<=n; i++) { scanf("%d",&t); add(t,i); } dfs(1); for(i=0; i<m; i++) { scanf("%s%d",q,&t); if(q[0]=='q') printf("%d\n",query(l[t],r[t],1,n,1)); else update(l[t],r[t],1,n,1); } printf("\n"); } return 0;}
- ZOJ 3686 A 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(dfs+线段树)
- ZOJ 3686-A Simple Tree Problem (DFS+线段树)
- 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(树转线段树+线段树区间更新)
- ZOJ 3686 A Simple Tree Problem(将对树的操作转化成区间=>线段树)
- ZOJ Monthly, March 2013 A题 A Simple Tree Problem(线段树)#zh
- BNU A Simple Tree Problem 线段树
- ZOJ3696-A Simple Tree Problem 线段树
- Hadoop源码学习_DatanodeID
- 双语阅读笔记 - 操作系统 - Process Control Block
- Android Developers:支持不同的屏幕大小
- 天猫宣布启动快递“当日达”
- [设计模式笔记]三. 行为型模式--25. Visitor模式(访问者)对象行为型模式(一)
- zoj 3686 (a simple tree problem)
- C#中Split用法
- 寻找发贴水王
- [设计模式笔记]三. 行为型模式--25. Visitor模式(访问者)对象行为型模式(二)
- 关于在 iOS 中支持 DLNA
- 博文2—c语言程序
- 开源 免费 java CMS - FreeCMS1.5-职位管理
- 一步一步学编程之Python(一)
- Java常用类库--正则表达式(Pattern类、Matcher类)