bzoj 4573 大森林

  • 由于树上路径是唯一的,查询合法的两个点间路径长度显然与其他加点操作无关,所以可以离线处理,将所有的查询放在加点后.
  • 这样我们可以对每棵树都在上颗树的基础上处理好形态后,处理这颗树上的询问.
  • 考虑若没有操作 \(1\) ,则所有树都一模一样.那么两棵树的形态不同,一定是某一颗执行了操作 \(1\) ,另一个却没有.只需要在每个关键位置(修改开始或结束时)将原来生长点所有子树挂到新的生长点下.
  • 若暴力移动子树,当子树数目较大时就会很劣.可以对每个操作 \(1\) 建立一个虚点,将这个操作内挂上去的点都挂在虚点上,于是只需要移动虚点就可以了.注意将虚点 \(siz\) 设置为 \(0\) .
  • 查询答案时,使用 \(dep[x]+dep[y]-2*dep[lca]\) 计算,避免虚点造成的影响.
  • 直接用 \(split(x,y)\) 会出问题.因为你把路径抠出来之后不知道要不要减去 \(1\) .
  1. #include<bits/stdc++.h>
  2. using namespace std;
  3. #define ll long long
  4. #define mp make_pair
  5. #define pii pair<int,int>
  6. inline int read()
  7. {
  8. int x=0;
  9. bool pos=1;
  10. char ch=getchar();
  11. for(;!isdigit(ch);ch=getchar())
  12. if(ch=='-')
  13. pos=0;
  14. for(;isdigit(ch);ch=getchar())
  15. x=x*10+ch-'0';
  16. return pos?x:-x;
  17. }
  18. const int MAXN=3e5+10;
  19. struct query{
  20. int pos,op,x,y;
  21. bool operator < (const query &rhs) const
  22. {
  23. return pos==rhs.pos?op<rhs.op:pos<rhs.pos;
  24. }
  25. }q[MAXN];
  26. namespace LCT{
  27. int stk[MAXN],tp;
  28. int tot;
  29. struct node{
  30. int ch[2],fa;
  31. int rev;
  32. int siz,val;
  33. node()
  34. {
  35. fa=ch[0]=ch[1]=0;
  36. rev=0;
  37. siz=val=0;
  38. }
  39. }tree[MAXN];
  40. #define root tree[x]
  41. #define lson tree[root.ch[0]]
  42. #define rson tree[root.ch[1]]
  43. inline void pushup(int x)
  44. {
  45. root.siz=lson.siz+root.val+rson.siz;
  46. }
  47. void inverse(int x)
  48. {
  49. swap(root.ch[0],root.ch[1]);
  50. root.rev^=1;
  51. }
  52. void pushdown(int x)
  53. {
  54. if(root.rev)
  55. {
  56. if(root.ch[0])
  57. inverse(root.ch[0]);
  58. if(root.ch[1])
  59. inverse(root.ch[1]);
  60. root.rev=0;
  61. }
  62. }
  63. bool isroot(int x)
  64. {
  65. int y=root.fa;
  66. return tree[y].ch[0]!=x && tree[y].ch[1]!=x;
  67. }
  68. void rotate(int x)
  69. {
  70. int y=tree[x].fa,z=tree[y].fa;
  71. int k=tree[y].ch[1]==x;
  72. if(!isroot(y))
  73. tree[z].ch[tree[z].ch[1]==y]=x;
  74. tree[x].fa=z;
  75. tree[tree[x].ch[k^1]].fa=y;
  76. tree[y].ch[k]=tree[x].ch[k^1];
  77. tree[x].ch[k^1]=y;
  78. tree[y].fa=x;
  79. pushup(y);
  80. pushup(x);
  81. }
  82. void splay(int x)
  83. {
  84. tp=0;
  85. stk[++tp]=x;
  86. for(int pos=x;!isroot(pos);pos=tree[pos].fa)
  87. stk[++tp]=tree[pos].fa;
  88. while(tp)
  89. pushdown(stk[tp--]);
  90. while(!isroot(x))
  91. {
  92. int y=tree[x].fa,z=tree[y].fa;
  93. if(!isroot(y))
  94. (tree[y].ch[0]==x)^(tree[z].ch[0]==y)?rotate(x):rotate(y);
  95. rotate(x);
  96. }
  97. pushup(x);
  98. }
  99. int Access(int x)
  100. {
  101. int y;
  102. for(y=0;x;y=x,x=tree[x].fa)
  103. {
  104. splay(x);
  105. tree[x].ch[1]=y;
  106. pushup(x);
  107. }
  108. return y;
  109. }
  110. void makeroot(int x)
  111. {
  112. Access(x);
  113. splay(x);
  114. inverse(x);
  115. }
  116. int findroot(int x)
  117. {
  118. Access(x);
  119. splay(x);
  120. while(tree[x].ch[0])
  121. x=tree[x].ch[0];
  122. return x;
  123. }
  124. void split(int x,int y)
  125. {
  126. makeroot(x);
  127. Access(y);
  128. splay(y);
  129. }
  130. void Link(int x,int y)
  131. {
  132. makeroot(x);
  133. tree[x].fa=y;
  134. }
  135. void Cut(int x)
  136. {
  137. Access(x);
  138. splay(x);
  139. tree[tree[x].ch[0]].fa=0;
  140. tree[x].ch[0]=0;
  141. pushup(x);
  142. }
  143. }
  144. using namespace LCT;
  145. int solve(int x,int y)
  146. {
  147. int ans=0;
  148. Access(x);
  149. splay(x);
  150. ans+=tree[x].siz;
  151. int lca=Access(y);
  152. splay(y);
  153. ans+=tree[y].siz;
  154. Access(lca);
  155. splay(lca);
  156. ans-=2*tree[lca].siz;
  157. return ans;
  158. }
  159. void newnode(int v)
  160. {
  161. int x=++tot;
  162. root.val=root.siz=v;
  163. }
  164. int n,m;
  165. int last,id[MAXN],idd,cnt,L[MAXN],R[MAXN],qs;
  166. inline void insq(int pos,int op,int x,int y)
  167. {
  168. ++cnt;
  169. q[cnt].pos=pos,q[cnt].op=op;
  170. q[cnt].x=x,q[cnt].y=y;
  171. }
  172. int ans[MAXN];
  173. int main()
  174. {
  175. tot=0;
  176. n=read(),m=read();
  177. newnode(1),idd=1,L[1]=1,R[1]=n,id[1]=1;
  178. newnode(0),last=2,Link(2,1);
  179. for(int i=1;i<=m;++i)
  180. {
  181. int type=read();
  182. if(type==0)
  183. {
  184. int l=read(),r=read();
  185. newnode(1);
  186. L[++idd]=l,R[idd]=r,id[idd]=tot;
  187. insq(1,i-m,tot,last);
  188. }
  189. else if(type==1)
  190. {
  191. int l=read(),r=read(),x=read();
  192. l=max(l,L[x]),r=min(r,R[x]);
  193. if(l<=r)
  194. {
  195. newnode(0);
  196. Link(tot,last);
  197. insq(l,i-m,tot,id[x]);
  198. insq(r+1,i-m,tot,last);
  199. last=tot;
  200. }
  201. }
  202. else
  203. {
  204. int x=read(),u=read(),v=read();
  205. insq(x,++qs,id[u],id[v]);
  206. }
  207. }
  208. sort(q+1,q+cnt+1);
  209. for(int i=1,j=1;i<=n;++i)
  210. {
  211. for(;j<=cnt && q[i].pos==i;++j)
  212. {
  213. if(q[j].op<=0)
  214. {
  215. Cut(q[j].x);
  216. Link(q[j].x,q[j].y);
  217. }
  218. else
  219. ans[q[j].op]=solve(q[j].x,q[j].y);
  220. }
  221. }
  222. for(int i=1;i<=qs;++i)
  223. printf("%d\n",ans[i]);
  224. return 0;
  225. }

bzoj 4573 大森林的更多相关文章

  1. [BZOJ 4573][ZJOI 2016]大森林

    [LOJ 2092][BZOJ 4573][UOJ 195][ZJOI 2016]大森林 题意 给定一个树序列, 初始时所有树都只有一个点, 要求支持三种操作: 区间种树(在某个特定点上长出一个子结点 ...

  2. 【刷题】BZOJ 4573 [Zjoi2016]大森林

    Description 小Y家里有一个大森林,里面有n棵树,编号从1到n.一开始这些树都只是树苗,只有一个节点,标号为1.这些树都有一个特殊的节点,我们称之为生长节点,这些节点有生长出子节点的能力.小 ...

  3. bzoj 4573: [Zjoi2016]大森林

    Description 小Y家里有一个大森林,里面有n棵树,编号从1到n.一开始这些树都只是树苗,只有一个节点,标号为1.这些树 都有一个特殊的节点,我们称之为生长节点,这些节点有生长出子节点的能力. ...

  4. BZOJ4573:[ZJOI2016]大森林——题解

    http://www.lydsy.com/JudgeOnline/problem.php?id=4573 https://www.luogu.org/problemnew/show/P3348#sub ...

  5. BZOJ 3684 大朋友和多叉树

    BZOJ 3684 大朋友和多叉树 Description 我们的大朋友很喜欢计算机科学,而且尤其喜欢多叉树.对于一棵带有正整数点权的有根多叉树,如果它满足这样的性质,我们的大朋友就会将其称作神犇的: ...

  6. 「ZJOI2016」大森林 解题报告

    「ZJOI2016」大森林 神仙题... 很显然线段树搞不了 考虑离线操作 我们只搞一颗树,从位置1一直往后移动,然后维护它的形态试试 显然操作0,1都可以拆成差分的形式,就是加入和删除 因为保证了操 ...

  7. [ZJOI2016]大森林(LCT)

    题目描述 小Y家里有一个大森林,里面有n棵树,编号从1到n.一开始这些树都只是树苗,只有一个节点,标号为1.这些树都有一个特殊的节点,我们称之为生长节点,这些节点有生长出子节点的能力. 小Y掌握了一种 ...

  8. [ZJOI2016]大森林

    Description: 小Y家里有一个大森林,里面有n棵树,编号从1到n 0 l r 表示将第 l 棵树到第 r 棵树的生长节点下面长出一个子节点,子节点的标号为上一个 0 号操作叶子标号加 1(例 ...

  9. [BZOJ 3652]大新闻

    [BZOJ 3652] 大新闻 题意 随机从 \([0,n)\) 中选取一个整数 \(x\), 并从 \([0,n)\) 中再选取一个整数 \(y\). 有 \(p\) 的概率选取一个能令 \(x\o ...

随机推荐

  1. POJ 3352 Road Construction(边—双连通分量)

    http://poj.org/problem?id=3352 题意: 给出一个图,求最少要加多少条边,能把该图变成边—双连通. 思路:双连通分量是没有桥的,dfs一遍,计算出每个结点的low值,如果相 ...

  2. codeforces291E Tree-String Problem

    本文版权归ljh2000和博客园共有,欢迎转载,但须保留此声明,并给出原文链接,谢谢合作. 本文作者:ljh2000 作者博客:http://www.cnblogs.com/ljh2000-jump/ ...

  3. hdu 4602 Partition 矩阵快速幂

    Partition Time Limit: 2000/1000 MS (Java/Others)    Memory Limit: 32768/32768 K (Java/Others) Proble ...

  4. 通过spring整合activeMQ实现jms实例

    写的很详细 http://blog.csdn.net/leonardo9029/article/details/43154385

  5. 关于IIS权限问题(Selenium WebDriver调用出错记录)

    本地VS调试过程中用Selenium WebDriver打开FF浏览器可以正常工作,项目部署至IIS后请求调用浏览器一直提示超时,异常如下: 因为本地调试可以成功,首先排除组件版本问题和浏览器兼容问题 ...

  6. Attribute 'items' must be an array, a Collection or a Map错误解决!

    唉!真的要说一句话叫做论一串代码的重要性!就是如此的气人!气的牙根痒痒! 前几天刚刚写过SpringMVC之ModelAndView的 jsp值在浏览页面不显示的问题!也是因为这一串代码,但是这一次一 ...

  7. cookie、session、sessionStorage、localStorage

    Cookie cookie是存储在浏览器端,并且随浏览器的请求一起发送到服务器端的,它有一定的过期时间,到了过期时间自动会消失. 首次设置cookie时是由服务器端发送到浏览器端 ,之后每次浏览器发送 ...

  8. 玲珑oj 1129 ST

    1129 - 喵哈哈村的战斗魔法师丶坏坏い月 Time Limit:3s Memory Limit:256MByte Submissions:490Solved:107 DESCRIPTION 坏坏い ...

  9. hdu3488

    题解: 首先把每一个点拆到两边 然后做KM求最大 吧没一条边相反即可 代码: #include<cstdio> #include<cmath> #include<algo ...

  10. 转载-lvs官方文档-Linux服务器集群系统(二)

    Linux服务器集群系统(二) LVS集群的体系结构 章文嵩 (wensong@linux-vs.org) 2002 年 4 月 本文主要介绍了LVS集群的体系结构.先给出LVS集群的通用体系结构,并 ...