题意:

  一棵n个节点的树,节点有黑白两种颜色,初始均为白色。两种操作:1.更改一个节点的颜色;2.询问一个节点所处的颜色相同的联通块的大小。

思路:

  1.每个节点记录仅考虑其子树时,假设其为黑色时所处的黑色联通块的大小和假设其为白色时所处的白色联通块的大小(树状数组维护)。
  2.查询时找到深度最小的、与该点颜色相同的且两点之间的点颜色均与这两点相同(两点可以重合)(不妨称它为最远祖先)的答案。
  3.修改时应该修改该节点的父亲至最远祖先的父亲上的值。
  4.用树链剖分和树状数组维护。
  5.寻找最远祖先时,跳重链,树状数组维护当前颜色(0为白 1为黑),查询重链上的颜色和,判断是否整段相同。是则继续向上跳,否则二分祖先。

反思:

  1.越上面的dfn越小,二分开始打反了(二分看了Po姐的)
  2.树链剖分有些生疏,开始时打错死循了。树状数组的应用不熟练。
  3.开始时修改时是边找最远祖先边修改的,结果在根周围时出现了问题。
  4.根在修改、查询时都特判一下,重链的端点为最远祖先时也特判一下。

代码:

  1. #include<cstdio>
  2. #define M 100005
  3. #define swap(x,y) u=x,x=y,y=u
  4. int n,u,cnt,dfn,p[M],v[M<<],id[M],co[M],sz[M],di[M],dep[M],top[M],hea[M],nex[M<<],ans[M][];
  5. bool col[M];
  6.  
  7. void ins(int x,int y) { v[++cnt]=y,nex[cnt]=hea[x],hea[x]=cnt; }
  8. void Add(int x,int y) { for (;x<=n;x+=x&-x) co[x]+=y; }
  9. int Ask(int x) { int s=; for (;x;x-=x&-x) s=s+co[x]; return s; }
  10. void add(int x,int y,bool c) { for (;x<=n;x+=x&-x) ans[x][c]+=y; }
  11. int ask(int x,bool c) { int s=; for (;x;x-=x&-x) s=s+ans[x][c]; return s;}
  12. bool pd(int x,int y,bool c)
  13. { return c && (Ask(y)-Ask(x-))==(y-x+) || (!c) && (Ask(x-)==Ask(y)); }
  14. int read()
  15. {
  16. int x=; char ch=getchar();
  17. for (;ch< || ch>;ch=getchar());
  18. for (;ch> && ch<;ch=getchar()) x=(x<<)+(x<<)+ch-;
  19. return x;
  20. }
  21.  
  22. void dfs(int x)
  23. {
  24. sz[x]=;
  25. for (int i=hea[x],y;i;i=nex[i])
  26. if ((y=v[i])^p[x]) p[y]=x,dep[y]=dep[x]+,dfs(y),sz[x]+=sz[y];
  27. }
  28.  
  29. void dfs(int x,int chain)
  30. {
  31. int i,k=,y;
  32. top[x]=chain,id[x]=++dfn,di[dfn]=x;
  33. for (i=hea[x];i;i=nex[i])
  34. if ((y=v[i])^p[x] && sz[y]>sz[k]) k=y;
  35. if (!k) return; dfs(k,chain);
  36. for (i=hea[x];i;i=nex[i])
  37. if ((y=v[i])^p[x] && y^k) dfs(y,y);
  38. }
  39.  
  40. void change(int x,int y,int v,bool c)
  41. {
  42. for (;top[x]!=top[y];x=p[top[x]])
  43. {
  44. if (dep[top[x]]<dep[top[y]]) swap(x,y);
  45. add(id[top[x]],v,c),add(id[x]+,-v,c);
  46. }
  47. if (dep[x]<dep[y]) swap(x,y);
  48. add(id[y],v,c),add(id[x]+,-v,c);
  49. }
  50.  
  51. int find(int x,bool c)
  52. {
  53. int l,r,t,y,mid;
  54. for (;x^;x=p[y])
  55. {
  56. l=id[y=top[x]],t=r=id[x];
  57. if (!pd(l,r,c))
  58. {
  59. while (l+<r)
  60. if (pd((mid=(l+r)>>),t,c)) r=mid; else l=mid+;
  61. if (pd(l,t,c)) return l; return r;
  62. }
  63. if (col[p[y]]^c) return l;
  64. }
  65. return ;
  66. }
  67.  
  68. int main()
  69. {
  70. n=read(); int i,x,y,m;
  71. for (i=;i<n;++i) x=read(),y=read(),ins(x,y),ins(y,x);
  72. dfs(p[]=),dfs(,),add(,,);
  73. for (i=;i<=n;++i) add(id[i],sz[i],),add(id[i]+,-sz[i],);
  74. for (m=read();m--;)
  75. {
  76. i=read(),x=read();
  77. if (i)
  78. {
  79. i=col[x];if (x-) change(p[x],p[di[find(x,i)]],-ask(id[x],i),i);
  80. if (i) Add(id[x],-); else Add(id[x],); col[x]^=;
  81. i=col[x];if (x-) change(p[x],p[di[find(x,i)]],ask(id[x],i),i);
  82. }
  83. else i=col[x],printf("%d\n",ask(find(x,i),i));
  84. }
  85. return ;
  86. }

bzoj3637 CodeChef SPOJ - QTREE6 Query on a tree VI 题解的更多相关文章

  1. SPOJ QTREE6 Query on a tree VI 树链剖分

    题意: 给出一棵含有\(n(1 \leq n \leq 10^5)\)个节点的树,每个顶点只有两种颜色:黑色和白色. 一开始所有的点都是黑色,下面有两种共\(m(1 \leq n \leq 10^5) ...

  2. QTREE6 - Query on a tree VI 解题报告

    QTREE6 - Query on a tree VI 题目描述 给你一棵\(n\)个点的树,编号\(1\)~\(n\).每个点可以是黑色,可以是白色.初始时所有点都是黑色.下面有两种操作请你操作给我 ...

  3. SPOJ 16549 - QTREE6 - Query on a tree VI 「一种维护树上颜色连通块的操作」

    题意 有操作 $0$ $u$:询问有多少个节点 $v$ 满足路径 $u$ 到 $v$ 上所有节点(包括)都拥有相同的颜色$1$ $u$:翻转 $u$ 的颜色 题解 直接用一个 $LCT$ 去暴力删边连 ...

  4. SPOJ QTREE Query on a tree VI

    You are given a tree (an acyclic undirected connected graph) with n nodes. The tree nodes are number ...

  5. SP16549 QTREE6 - Query on a tree VI LCT维护颜色联通块

    \(\color{#0066ff}{ 题目描述 }\) 给你一棵n个点的树,编号1~n.每个点可以是黑色,可以是白色.初始时所有点都是黑色.下面有两种操作请你操作给我们看: 0 u:询问有多少个节点v ...

  6. [QTree6]Query on a tree VI

    Description: 给你一棵n个点的树,编号1~n.每个点可以是黑色,可以是白色.初始时所有点都是黑色.下面有两种操作请你操作给我们看: 0 u:询问有多少个节点v满足路径u到v上所有节点(包括 ...

  7. 洛谷SP16549 QTREE6 - Query on a tree VI(LCT)

    洛谷题目传送门 思路分析 题意就是要维护同色连通块大小.要用LCT维护子树大小就不说了,可以看看蒟蒻的LCT总结. 至于连通块如何维护,首先肯定可以想到一个很naive的做法:直接维护同色连通块,每次 ...

  8. SP16549 QTREE6 - Query on a tree VI(LCT)

    题意翻译 题目描述 给你一棵n个点的树,编号1~n.每个点可以是黑色,可以是白色.初始时所有点都是黑色.下面有两种操作请你操作给我们看: 0 u:询问有多少个节点v满足路径u到v上所有节点(包括)都拥 ...

  9. bzoj 3637: Query on a tree VI 树链剖分 && AC600

    3637: Query on a tree VI Time Limit: 8 Sec  Memory Limit: 1024 MBSubmit: 206  Solved: 38[Submit][Sta ...

随机推荐

  1. Execution of 'source /usr/hdp/current/oozie-server/conf/oozie--env.sh: oozie admin -oozie http://nssa-sensor3:11000/oozie -status' returned 255.解决办法(图文详解)

    不多说,直接上干货! 问题详情 解决办法 Copy/Paste oozie.services property tag set from oozie-default.xml to oozie-site ...

  2. PowerShell~执行策略的介绍

    首先看一下无法加载ps1脚本的解决方法 事实上也是由于策略导致的  解决方法主是开启对应的策略 set-ExecutionPolicy RemoteSigned 执行策略更改 执行策略可以防止您执行不 ...

  3. android开发学习 ------- git - 将代码回滚到任意版本

    不小心将一个东西错误提交到git - 远程仓库上 参考  https://www.cnblogs.com/wancy86/p/5848024.html 你的git可能关联了多个远程仓库,每个关联的代码 ...

  4. 使用kubeadm安装kubernetes v1.14.1

    使用kubeadm安装kubernetes v1.14.1 一.环境准备 操作系统:Centos 7.5 ​ ⼀ 一台或多台运⾏行行着下列列系统的机器器: ​ Ubuntu 16.04+ ​ Debi ...

  5. TextView、EditText

    1.TextView     显示文本信息 常用属性: layout_width/height    控件的宽/高 width/heigth    文本区域的宽/高 text 显示的文本 textSi ...

  6. 一份最贴近真实面试的Java基础面试题

    这是一份Java基础知识的面试题.在网上的关于Java的面试题数不胜数,但认真看过感觉大多数都没有实用性,有很多是面试官根本就不会问到的,那些已经脱离了实际开发的技术问题.而这份资料来源自一份个人觉得 ...

  7. windows.old文件删除

    在安装完新系统后,会发现C盘下有个windows.old文件夹,大约有个10多G,里面都是对之前系统的一些备份,用于对之前系统恢复时使用,一般一个月后会自动清理,若觉得不会再对系统进行老版本恢复时,又 ...

  8. Linux 使用常见问题

    1. 如何查看软件安装到什么位置 [Ubuntu] 今天安装了Lxc-docker,想看一下文件都安装到哪里了,首先找到这个包的ersion zhouh1@uhome:~$ dpkg -s lxc-d ...

  9. 实战角度比较EJB2和EJB3的架构异同

    ] EJB编程模型的简化 首先,EJB3简化的一个主要表现是:在EJB3中,一个EJB不再象EJB2中需要两个接口一个Bean实现类,虽然我们以前使用JBuilder这样可视化开发工具自动生成了EJB ...

  10. codevs 1219 骑士游历 1997年

    时间限制: 1 s  空间限制: 128000 KB  题目等级 : 黄金 Gold 题目描述 Description 设有一个n*m的棋盘(2≤n≤50,2≤m≤50),如下图,在棋盘上有一个中国象 ...