Luogu3348

BZOJ4573

LOJ2092

题解

对于每个\(1\)操作建一个虚点,以后的\(0\)操作都连在最近建好的虚点上。这样每次整体嫁接的时候,直接把这个虚点断掉它原来的父亲,再\(link\)过去就可以了

求在\(x\)位置的两点之间距离 , 只要之前的换点加点操作完成 , 就可以计算 , 而且也要马上计算 , 之后树的形态就又要变了 , 这样保证了复杂度

关于代码 : 先按思路把离线的事件处理出来

然后发现这种离线的利用虚点的转移只能用\(LCT\)维护

注意 : 只有实点才算\(size\) , 并统计到路径长度中去 , 利用的虚点不算\(size\)

还有\(LCT\)上不\(makeroot\)时求\(LCA\)的求法

注释重构于19.3.29

  1. #include<cstdio>
  2. #include<cstring>
  3. #include<algorithm>
  4. #include<iostream>
  5. #define debug(...) fprintf(stderr,__VA_ARGS__)
  6. #define Debug(x) cout<<#x<<"="<<x<<endl
  7. using namespace std;
  8. typedef long long LL;
  9. const int INF=1e9+7;
  10. inline LL read(){
  11. register LL x=0,f=1;register char c=getchar();
  12. while(c<48||c>57){if(c=='-')f=-1;c=getchar();}
  13. while(c>=48&&c<=57)x=(x<<3)+(x<<1)+(c&15),c=getchar();
  14. return f*x;
  15. }
  16. const int MAXN=3e5+5;
  17. const int MAXM=2e5+5;
  18. struct Query{
  19. int pos,id,x,y;
  20. inline friend bool operator<(Query a,Query b){
  21. if(a.pos==b.pos) return a.id<b.id;
  22. return a.pos<b.pos;
  23. }
  24. }q[MAXM];
  25. int Qcnt,Acnt;
  26. int at[MAXN],L[MAXN],R[MAXN],ans[MAXN];
  27. int n,m,p,aux,real;
  28. namespace LCT{
  29. int ch[MAXN][2],fa[MAXN],size[MAXN],val[MAXN];
  30. int st[MAXN],top;
  31. #define ls (ch[rt][0])
  32. #define rs (ch[rt][1])
  33. inline bool chk(int x){return ch[fa[x]][1]==x;}
  34. inline bool isnotroot(int x){return ch[fa[x]][0]==x||ch[fa[x]][1]==x;}
  35. inline void pushup(int rt){size[rt]=size[ls]+size[rs]+val[rt];}//只要算实点
  36. inline void rotate(int x){
  37. int y=fa[x],z=fa[y],k=chk(x),w=ch[x][k^1];
  38. ch[y][k]=w,fa[w]=y;
  39. if(isnotroot(y)) ch[z][chk(y)]=x; fa[x]=z;
  40. ch[x][k^1]=y,fa[y]=x;
  41. pushup(y);pushup(x);
  42. }
  43. inline void splay(int x){
  44. while(isnotroot(x)){
  45. int y=fa[x];
  46. if(isnotroot(y)){
  47. if(chk(x)==chk(y)) rotate(y);
  48. else rotate(x);
  49. }
  50. rotate(x);
  51. }
  52. }
  53. inline int access(int x){
  54. int y=0;
  55. for(;x;x=fa[y=x])
  56. splay(x),ch[x][1]=y,pushup(x);
  57. return y;//access(y)时最后跳的虚边的父亲就是lca,即最后的y
  58. }
  59. inline void link(int x,int y){
  60. splay(x);//不能makeroot,只能splay
  61. fa[x]=y;//只有根节点才能连边
  62. }
  63. inline void cut(int x){//和它上面的点断开
  64. access(x);splay(x);
  65. ch[x][0]=fa[ch[x][0]]=0;
  66. pushup(x);
  67. }
  68. #undef ls
  69. #undef rs
  70. }using namespace LCT;
  71. int main(){
  72. n=read(),m=read();
  73. real=1,size[1]=1,val[1]=1,at[1]=1,L[1]=1,R[1]=n;//初始时只有1一个实点
  74. link(p=aux=2,1);
  75. for(int i=1;i<=m;i++){
  76. int op=read(),x=read(),y=read();
  77. if(op==0){
  78. link(at[++real]=++p,aux);///新建一个点连到虚点上去,并记录第real个实点在哪(是所有编号中的第几个)
  79. size[p]=1,val[p]=1;//更新val[]!!! (注意只有这样的实点才有权值)
  80. L[real]=x,R[real]=y;
  81. }
  82. if(op==1){
  83. int t=read();
  84. x=max(x,L[t]),y=min(y,R[t]);//有些树还没这个点
  85. if(x>y) continue;
  86. link(++p,aux);///新建一个点连到虚点上去
  87. //size[p]=0,val[p]=0; 虚点没有val[],不算进路径上有size[]个点
  88. //先按思路把离线的事件处理出来
  89. q[++Qcnt]=(Query){x,i-m,p,at[t]};///到了x就把虚点换成这个 -m是为了使换点操作在加点操作前面.
  90. q[++Qcnt]=(Query){y+1,i-m,p,aux};//到了y+1就换回去
  91. aux=p;//更换虚点了!!! 之后的点要放到新点的下面
  92. }
  93. if(op==2) q[++Qcnt]=(Query){x,++Acnt,at[y],at[read()]};//在x位置的两点之间距离,只要之前的换点加点操作完成,就可以计算,而且也要马上计算,之后树的形态就又要变了
  94. }
  95. sort(q+1,q+Qcnt+1);
  96. for(int i=1;i<=Qcnt;i++){
  97. if(q[i].id>0){
  98. int x=q[i].x,y=q[i].y,&sum=ans[q[i].id];
  99. //由于根节点始终为1,不能makeroot后求路径,所以要用到lca.本题中步数=size[x]+size[y]-2*size[lca].
  100. access(x);splay(x);sum+=size[x];
  101. int lca=access(y);splay(y);sum+=size[y];
  102. access(lca);splay(lca);sum-=size[lca]*2;//打起来真的舒服
  103. }
  104. else{ // 这种离线的利用虚点的转移只能用LCT维护
  105. cut(q[i].x);//和它上面的点断开
  106. link(q[i].x,q[i].y);//然后连到新的点上去
  107. }
  108. }
  109. for(int i=1;i<=Acnt;i++)
  110. printf("%d\n",ans[i]);
  111. }

P3348 [ZJOI2016]大森林(LCT)的更多相关文章

  1. 洛谷P3348 [ZJOI2016]大森林 [LCT]

    传送门 刷了那么久水题之后终于有一题可以来写写博客了. 但是这题太神仙了我还没完全弄懂-- upd:写完博客之后似乎懂了. 思路 首先很容易想到\(O(n^2\log n)\)乘上\(O(\frac{ ...

  2. [ZJOI2016]大森林(LCT)

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

  3. P3348 [ZJOI2016]大森林

    \(\color{#0066ff}{ 题目描述 }\) 小Y家里有一个大森林,里面有n棵树,编号从1到n.一开始这些树都只是树苗,只有一个节点,标号为1.这些树都有一个特殊的节点,我们称之为生长节点, ...

  4. 洛谷P3348 [ZJOI2016]大森林(LCT,虚点,树上差分)

    洛谷题目传送门 思路分析 最简单粗暴的想法,肯定是大力LCT,每个树都来一遍link之类的操作啦(T飞就不说了) 考虑如何优化算法.如果没有1操作,肯定每个树都长一样.有了1操作,就来仔细分析一下对不 ...

  5. ●洛谷P3348 [ZJOI2016]大森林

    题链: https://www.luogu.org/problemnew/show/P3348 题解: LCT,神题 首先有这么一个结论: 每次的1操作(改变生长点操作),一定只会会对连续的一段区间产 ...

  6. bzoj 4573: [Zjoi2016]大森林 lct splay

    http://www.lydsy.com/JudgeOnline/problem.php?id=4573 http://blog.csdn.net/lych_cys/article/details/5 ...

  7. P3348 [ZJOI2016]大森林(Link-cut-tree)

    传送门 题解 题面大意: \(0.\)区间加节点 \(1.\)区间换根 \(2.\)单点询问距离 如果没有\(1\)操作,因为区间加节点都是加在下面,所以我们可以直接把\(n\)棵树压成一棵树,直接询 ...

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

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

  9. [ZJOI2016]大森林

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

随机推荐

  1. DAY4-函数进阶

    目录: 一.迭代器 二.生成器 三.面向过程编程 四.三元表达式.列表推导式.生成器表达式 五.第归与二分法 六.匿名函数 七.内置函数 练习 一.迭代器 一.迭代的概念 #迭代器即迭代的工具,那什么 ...

  2. centos7部署func

    Func(Fedora Unitied Network Controller)是红帽公司以Fedora平台构建的统一网络控制器,是为解决集群管理.监控问题而设计开发的系统管理基础框架.它是一个能有效简 ...

  3. 经典的CSS代码(转)

    Web开发技术每年都在革新,浏览器已逐渐支持CSS3特性,并且网站设计师和前端开发者普遍采用这种新技术进行设计与开发.但仍然有一些开发者迷恋着一些CSS2代码. 分享20段非常专业的CSS2/CSS3 ...

  4. QT5环境搭建

    https://blog.csdn.net/liang19890820/article/details/53931813

  5. 基于Opengl的太阳系动画实现

    #include <GL\glut.h> float fEarth = 2.0f;//地球绕太阳的旋转角度float fMoon = 24.0f;//月球绕地球的旋转角度 void Ini ...

  6. Java-马士兵设计模式学习笔记-工厂模式-简单工厂

    一.概述 1.目标:要控制任意类型交通工具的生产模式 2.目标有两层意思(1)任意类型 (2)生产模式,所以对应的,要这两个层面上抽象(Movable,VehicleFactory),利用接口,实现多 ...

  7. c++ vitual继承

    为了解决多继承下的二义性而设计的vitrul继承 class Base { public: Base(void); ~Base(void); }; Base::Base(void) { printf( ...

  8. python3-函数的参数的四种简单用法:

    def print_two(*args):     arg1, arg2 = args     print "arg1: %r, arg2: %r" % (arg1,arg2)   ...

  9. Newtonsoft Json操作类库的使用

    1.解析简单Json字符串 if (l_sSenJson != "") { JObject obj2 = (JObject)JsonConvert.DeserializeObjec ...

  10. review backpropagation

    The goal of backpropagation is to compute the partial derivatives ∂C/∂w and ∂C/∂b of the cost functi ...