原题: ZOJ 3686 http://acm.zju.edu.cn/onlinejudge/showProblem.do?problemCode=3686

这题本来是一个比较水的线段树,结果一个mark坑了我好几个小时。。哎。太弱。

先DFS这棵树,树形结构转换为线性结构,每个节点有一个第一次遍历的时间和最后一次遍历的时间,之间的时间戳都为子树的时间戳,用线段树更新这段区间即可实现更新子树的效果,用到懒操作节省时间。

坑我的地方: update时,不能写成:tree[rt].mark = 1, 而要写成 tree[rt].mark ^= 1; 因为如果持续update偶数次相当于什么都没做,但是每次update确实是更新了的啊,每次pushdown都会将tree[rt].mark变为0的啊,也就是说tree[rt].mark是不能保持的,所以我搞不懂的是为什么要异或1,而不能直接令等于1,有待向大神请教,如果有看到并知道的仁兄可以指教一下我。

代码:

  1. #include <iostream>
  2. #include <cstdio>
  3. #include <cstring>
  4. #include <cmath>
  5. #include <algorithm>
  6. #include <vector>
  7. using namespace std;
  8. #define N 100007
  9.  
  10. struct node
  11. {
  12. int l,r;
  13. }p[N];
  14.  
  15. struct Tree
  16. {
  17. int sum,mark;
  18. }tree[*N];
  19. int Time;
  20. vector<int> G[N];
  21.  
  22. void pushup(int rt)
  23. {
  24. tree[rt].sum = tree[*rt].sum + tree[*rt+].sum;
  25. }
  26.  
  27. void build(int l,int r,int rt)
  28. {
  29. tree[rt].sum = tree[rt].mark = ;
  30. if(l == r)
  31. return;
  32. int mid = (l+r)/;
  33. build(l,mid,*rt);
  34. build(mid+,r,*rt+);
  35. pushup(rt);
  36. }
  37.  
  38. void pushdown(int l,int r,int rt)
  39. {
  40. if(!tree[rt].mark)
  41. return;
  42. int mid = (l+r)/;
  43. tree[*rt].mark ^= ; //not "tree[2*rt].mark = tree[rt].mark"
  44. tree[*rt+].mark ^= ;
  45. tree[*rt].sum = (mid-l+)-tree[*rt].sum;
  46. tree[*rt+].sum = (r-mid)-tree[*rt+].sum;
  47. tree[rt].mark = ;
  48. }
  49.  
  50. void update(int l,int r,int aa,int bb,int rt)
  51. {
  52. if(aa<=l && bb>=r)
  53. {
  54. tree[rt].mark ^= ; //not "tree[rt].mark = 1", 因为偶数次操作相互抵消
  55. tree[rt].sum = r-l+-tree[rt].sum;
  56. return;
  57. }
  58. pushdown(l,r,rt);
  59. int mid = (l+r)/;
  60. if(aa <= mid)
  61. update(l,mid,aa,bb,*rt);
  62. if(bb > mid)
  63. update(mid+,r,aa,bb,*rt+);
  64. pushup(rt);
  65. }
  66.  
  67. void dfs(int u)
  68. {
  69. p[u].l = Time++;
  70. for(int i=;i<G[u].size();i++)
  71. dfs(G[u][i]);
  72. p[u].r = Time++;
  73. }
  74.  
  75. int query(int l,int r,int aa,int bb,int rt)
  76. {
  77. if(aa>r || bb<l)
  78. return ;
  79. if(aa<=l && bb>=r)
  80. return tree[rt].sum;
  81. pushdown(l,r,rt);
  82. int mid = (l+r)/;
  83. return query(l,mid,aa,bb,*rt)+query(mid+,r,aa,bb,*rt+);
  84. }
  85.  
  86. int main()
  87. {
  88. int n,m,i,j,x;
  89. char ss[];
  90. while(scanf("%d%d",&n,&m)!=EOF)
  91. {
  92. for(i=;i<=n;i++)
  93. G[i].clear();
  94. for(i=;i<=n;i++)
  95. {
  96. scanf("%d",&x);
  97. G[x].push_back(i);
  98. }
  99. Time = ;
  100. dfs();
  101. build(,*n,);
  102. while(m--)
  103. {
  104. scanf("%s%d",ss,&x);
  105. if(ss[] == 'o')
  106. update(,*n,p[x].l,p[x].r,);
  107. else
  108. printf("%d\n",query(,*n,p[x].l,p[x].r,)/);
  109. }
  110. puts("");
  111. }
  112. return ;
  113. }

2014 Super Training #9 F A Simple Tree Problem --DFS+线段树的更多相关文章

  1. ZOJ 3686 A Simple Tree Problem(线段树)

    Description Given a rooted tree, each node has a boolean (0 or 1) labeled on it. Initially, all the ...

  2. zoj 3686 A Simple Tree Problem (线段树)

    Solution: 根据树的遍历道的时间给树的节点编号,记录下进入节点和退出节点的时间.这个时间区间覆盖了这个节点的所有子树,可以当做连续的区间利用线段树进行操作. /* 线段树 */ #pragma ...

  3. 2014 Super Training #7 F Power of Fibonacci --数学+逆元+快速幂

    原题:ZOJ 3774  http://acm.zju.edu.cn/onlinejudge/showProblem.do?problemCode=3774 --------------------- ...

  4. 2014 Super Training #6 F Search in the Wiki --集合取交+暴力

    原题: ZOJ 3674 http://acm.zju.edu.cn/onlinejudge/showProblem.do?problemCode=3674 题意不难理解,很容易想到用暴力,但是无从下 ...

  5. 2014 Super Training #2 F The Bridges of Kolsberg --DP

    原题:UVA 1172  http://uva.onlinejudge.org/index.php?option=com_onlinejudge&Itemid=8&page=show_ ...

  6. 2014 Super Training #1 F Passage 概率DP

    原题: HDU 3366   http://acm.hdu.edu.cn/showproblem.php?pid=3366 本来用贪心去做,怎么都WA,后来看网上原来是一个DP题. 首先按P/Q来做排 ...

  7. 2014 Super Training #10 C Shadow --SPFA/随便搞/DFS

    原题: FZU 2169 http://acm.fzu.edu.cn/problem.php?pid=2169 这题貌似有两种解法,DFS和SPFA,但是DFS怎么都RE,SPFA也要用邻接表表示边, ...

  8. ZOJ 3686 A Simple Tree Problem

    A Simple Tree Problem Time Limit: 3 Seconds      Memory Limit: 65536 KB Given a rooted tree, each no ...

  9. BNU 28887——A Simple Tree Problem——————【将多子树转化成线段树+区间更新】

    A Simple Tree Problem Time Limit: 3000ms Memory Limit: 65536KB This problem will be judged on ZJU. O ...

随机推荐

  1. android.widget.RadioButton 单选按钮(转)

    大家好,我们今天这一节要介绍的是RadioGroup 的组事件.RadioGroup 可将各自不同的RadioButton ,设限于同一个Radio 按钮组,同一个RadioGroup 组里的按钮,只 ...

  2. .NET WinForm画树叶小程序

    看了一片文章(http://keleyi.com/a/bjac/nurox416.htm),是使用分型画树叶,代码是Java的,因为Java很久没弄了,改用C#实现,下载地址: 画树叶小程序下载 核心 ...

  3. XStream的例子

    写个小例子,方便以后复习: 1 package com.demo; 2 3 import java.util.ArrayList; 4 import java.util.List; 5 6 impor ...

  4. CentOS6.5上编译OpenJDK7源码

    本文地址:http://www.cnblogs.com/wuyudong/p/build-openjdk7.html,转载请注明源地址. 采用开源的OpenJDK版本,获取其源码的方式有两种: 通Me ...

  5. Android ListView用EditText实现搜索功能

    前言 最近在开发一个IM项目的时候有一个需求就是,好友搜索功能.即在EditText中输入好友名字,ListView列表中动态展示刷选的好友列表.我把这个功能抽取出来了,先贴一下效果图: 分析 在查阅 ...

  6. 自定义控件--CircleImageView(类似于QQ、微信圆形头像自定义控件)

    现在基本上所有的需要用户注册的APP都有一个需要用户上传头像的需求,上传的头像基本都是类似于QQ.微信等社交应用圆形头像.最近,正在做的一个社交应用多处需要用到这种圆形头像的处理,总不能每次都对图片做 ...

  7. 可折叠的ToolBar+抽屉菜单NavigationView+浮动按钮FloatButton

    使用Material Design风格的ToolBar和抽屉导航 先看个简单的运行效果 主要记录下布局的写法 1 用到的Google Design依赖和V7包依赖 compile 'com.andro ...

  8. 如何创建可扩展表视图中的iOS 学习和拓展优化(有待更新)

    首先介绍老外的文章:<How To Create an Expandable Table View in iOS>这是老外用Swift实现 的,对应的老外github项目源码:https: ...

  9. 导出excel乱码问题

    今天遇到一个问题,在用C#做导出excel的时候,出现excel乱码问题.百度了下. 发现问题如下: 非中文字符编码问题. 解决方法: 把输出的excel格式设置成UTF-8即可. 更改代码: Res ...

  10. 敏捷开发中高质量 Java 代码开发实践

    Java 项目开发过程中,由于开发人员的经验.代码风格各不相同,以及缺乏统一的标准和管理流程,往往导致整个项目的代码质量较差,难于维护,需要较大的测试投入 和周期等问题. 这些问题在一个项目组初建.需 ...