1. --少年你有梦想吗?
  2. --少年你听说过安利吗?

安利一个集训队讲解:http://wenku.baidu.com/view/75906f160b4e767f5acfcedb

关于动态树问题,有多种方法。。LCT是其中比较常用的方法;

  1. LCT这种东西根本没用----by ShallWe
  2. ----你真的确定吗(charge
  3. 我之前非常确定。
  4. 。。。。。。。。。

LCT的话,比较类似树链剖分,有类似轻重链的东东Preferred Path。不过链剖是用线段树维护,而LCT应用伸展树Splay维护。按深度维护。

动态树可以维护一个动态的森林,支持树的合并(两棵合并成一棵),分离(把某个点和它父亲点分开),动态LCA,树上的点权和边权维护、查询(单点或者树上的一条路径),换根。

具体的几个操作:

Access操作:大体上就是访问这个点。

是所有操作的基础,假设调用了过程ACCESS(v),那么从点v到根结点的路径就成为一条新的PreferredPath.如果路径上经过的某个结点u并不是它的父亲parent(u)的Pre-ferredChild,那么由于parent(u)的PreferredChild会变为u,原本包含parent(u)的PreferredPath将不再包含结点parent(u)及其之上的部分.

时间复杂度是均摊的logn证明详见开头的论文。。

Find_Root操作:在ACCESS(v)之后,根结点一定是v所属的AuxiliaryTree的最小结点.我们先把v旋转到它所属的AuxiliaryTree的根.再从v开始,沿着AuxiliaryTree向左走,直到不能再向左,这个点就是我们要找的根结点.由于使用的是SplayTree数据结构保存AuxiliaryTree,我们还需要对根结点进行Splay操作.

Link操作:进行合并

Cut操作:将之分离

  1. (其实最开始想写指针的QAQ,调不出来TAT)感谢Claris的代码帮助

[应用]

1、 最近公共祖先

询问v,w的最近公共祖先,首先执行access(v),再执行access(w),当执行access(w)时,记录最近的一个再上次access中被访问的点,这个点就是最近公共祖先。

每次询问需要O(logN)时间。 2、 集合的合并与分离

可以支持Link和Find操作,还能支持以某种方式分离,而每个集合操作的时间复杂度为O(logN) 3、 最大流

动态树可以用来优化最短路径增广算法,使每次增广的复杂度降为O(mlogN),并使总复杂度为O(mnlogN)。 4、 最小生成树

动态树在最小生成树问题中有许多应用。 比如,最小生成树的增量算法、度限制生成树。还有其他许多种变形

模板:(可以压到很短的,抱歉我又刷屏了)

  1. #include<iostream>
  2. #include<cstdio>
  3. #include<algorithm>
  4. #include<cstring>
  5. #include<cmath>
  6. using namespace std;
  7. #define N 10010
  8. int f[N],son[N][2],val[N],sum[N],tmp[N];bool rev[N];
  9. bool isroot(int x)
  10. {
  11. return !f[x]||son[f[x]][0]!=x&&son[f[x]][1]!=x;
  12. }//判根
  13. void rev1(int x)
  14. {
  15. if(!x) return;
  16. swap(son[x][0],son[x][1]);
  17. rev[x]^=1;
  18. }//翻转
  19. void pb(int x)
  20. {
  21. if(rev[x])
  22. rev1(son[x][0]),rev1(son[x][1]),rev[x]=0;
  23. }//翻转
  24. void up(int x)
  25. {
  26. sum[x]=val[x];
  27. if(son[x][0])sum[x]+=sum[son[x][0]];
  28. if(son[x][1])sum[x]+=sum[son[x][1]];
  29. }//更新值
  30. void rotate(int x)
  31. {
  32. int y=f[x],w=son[y][1]==x;
  33. son[y][w]=son[x][w^1];
  34. if(son[x][w^1]) f[son[x][w^1]]=y;
  35. if(f[y])
  36. {
  37. int z=f[y];
  38. if(son[z][0]==y)son[z][0]=x;
  39. else if(son[z][1]==y)son[z][1]=x;
  40. }
  41. f[x]=f[y];f[y]=x;
  42. son[x][w^1]=y;up(y);
  43. }//旋转
  44. void splay(int x)
  45. {
  46. int s=1,i=x,y;tmp[1]=i;
  47. while(!isroot(i)) tmp[++s]=i=f[i];
  48. while(s) pb(tmp[s--]);
  49. while(!isroot(x))
  50. {
  51. y=f[x];
  52. if(!isroot(y))
  53. {
  54. if((son[f[y]][0]==y)^(son[y][0]==x))
  55. rotate(x); else rotate(y);
  56. }
  57. rotate(x);
  58. }
  59. up(x);
  60. }//伸展
  61. void access(int x)
  62. {
  63. for(int y=0;x;y=x,x=f[x])
  64. splay(x),son[x][1]=y,up(x);
  65. }//访问
  66. int root(int x)
  67. {
  68. access(x);splay(x);
  69. while(son[x][0]) x=son[x][0];
  70. return x;
  71. }//换根
  72. void makeroot(int x)
  73. {
  74. access(x);
  75. splay(x);
  76. rev1(x);
  77. }
  78. void link(int x,int y)
  79. {
  80. makeroot(x);
  81. f[x]=y;
  82. access(x);
  83. }
  84. void cutf(int x)
  85. {
  86. access(x);
  87. splay(x);
  88. f[son[x][0]]=0;
  89. son[x][0]=0;
  90. up(x);
  91. }
  92. void cut(int x,int y)
  93. {
  94. makeroot(x);
  95. cutf(y);
  96. }//分离
  97. int ask(int x,int y)
  98. {
  99. makeroot(x);
  100. access(y);
  101. splay(y);
  102. return sum[y];
  103. }//查询值
  104. int find(int x)
  105. {
  106. access(x);
  107. splay(x);
  108. int y=x;
  109. while(son[y][0]) y=son[y][0];
  110. return y;
  111. }//判断连通性(类LCA)
  112. int main()
  113. {
  114. return 0;
  115. }

学习笔记-动态树Link-Cut-Tree的更多相关文章

  1. 动态树(Link Cut Tree) :SPOJ 375 Query on a tree

    QTREE - Query on a tree #number-theory You are given a tree (an acyclic undirected connected graph) ...

  2. 【学习笔记】LCT link cut tree

    大概就是供自己复习的吧 1. 细节讲解 安利两篇blog: Menci 非常好的讲解与题单 2.模板 把 $ rev $ 和 $ pushdown $ 的位置记清 #define lc son[x][ ...

  3. LCT总结——概念篇+洛谷P3690[模板]Link Cut Tree(动态树)(LCT,Splay)

    为了优化体验(其实是强迫症),蒟蒻把总结拆成了两篇,方便不同学习阶段的Dalao们切换. LCT总结--应用篇戳这里 概念.性质简述 首先介绍一下链剖分的概念(感谢laofu的讲课) 链剖分,是指一类 ...

  4. Link Cut Tree学习笔记

    从这里开始 动态树问题和Link Cut Tree 一些定义 access操作 换根操作 link和cut操作 时间复杂度证明 Link Cut Tree维护链上信息 Link Cut Tree维护子 ...

  5. P3690 【模板】Link Cut Tree (动态树)

    P3690 [模板]Link Cut Tree (动态树) 认父不认子的lct 注意:不 要 把 $fa[x]$和$nrt(x)$ 混 在 一 起 ! #include<cstdio> v ...

  6. 【刷题】洛谷 P3690 【模板】Link Cut Tree (动态树)

    题目背景 动态树 题目描述 给定n个点以及每个点的权值,要你处理接下来的m个操作.操作有4种.操作从0到3编号.点从1到n编号. 0:后接两个整数(x,y),代表询问从x到y的路径上的点的权值的xor ...

  7. LuoguP3690 【模板】Link Cut Tree (动态树) LCT模板

    P3690 [模板]Link Cut Tree (动态树) 题目背景 动态树 题目描述 给定n个点以及每个点的权值,要你处理接下来的m个操作.操作有4种.操作从0到3编号.点从1到n编号. 0:后接两 ...

  8. 学习笔记:Link Cut Tree

    模板题 原理 类似树链剖分对重儿子/长儿子剖分,Link Cut Tree 也做的是类似的链剖分. 每个节点选出 \(0 / 1\) 个儿子作为实儿子,剩下是虚儿子.对应的边是实边/虚边,虚实时可以进 ...

  9. LG3690 【模板】Link Cut Tree (动态树)

    题意 给定n个点以及每个点的权值,要你处理接下来的m个操作.操作有4种.操作从0到3编号.点从1到n编号. 0:后接两个整数(x,y),代表询问从x到y的路径上的点的权值的xor和.保证x到y是联通的 ...

随机推荐

  1. MySQL数据库学习笔记(六)----MySQL多表查询之外键、表连接、子查询、索引

    本章主要内容: 一.外键 二.表连接 三.子查询 四.索引 一.外键: 1.什么是外键 2.外键语法 3.外键的条件 4.添加外键 5.删除外键 1.什么是外键: 主键:是唯一标识一条记录,不能有重复 ...

  2. java 21 - 13 IO流之 合并流

    SequenceInputStream :表示其他输入流的逻辑串联. 构造方法摘要 SequenceInputStream(Enumeration<? extends InputStream&g ...

  3. java 13-2 Arrays工具类

    1.Arrays:针对数组进行操作的工具类.比如说排序和查找. 1:public static String toString(int[] a) 把数组转成字符串  2:public static v ...

  4. ubuntu 命令收集

    1. ctrl + Alt + F1:   进入纯粹的命令行. 2. ctr + Alt + T :    从图形界面打开终端.

  5. 浏览器默认样式(User Agent Stylesheet)

    原文:http://www.zjgsq.com/898.html 不同浏览器对于相同元素的默认样式并不一致,这也是为什么我们在CSS的最开始要写 * {padding:0;marging:0}: 不过 ...

  6. 【转】【C#】【Thread】Mutex 互斥锁

    Mutex:互斥(体) 又称同步基元. 当创建一个应用程序类时,将同时创建一个系统范围内的命名的Mutex对象.这个互斥元在整个操作系统中都是可见的.当已经存在一个同名的互斥元时,构造函数将会输出一个 ...

  7. [转]iOS 应用内付费(IAP)开发步骤

    FROM : http://blog.csdn.net/xiaoxiangzhu660810/article/details/17434907 参考文章链接: (1)http://mobile.51c ...

  8. [WEB API] CLIENT 指定请求及回应格式(XML/JSON)

    [Web API] Client 指定请求及响应格式(xml/json) Web API 支持的格式请参考 http://www.asp.net/web-api/overview/formats-an ...

  9. python 转 exe -- py2exe库实录

    本文基于windows 7 + python 3.4 把python程序打包成exe,比较好用的库是py2exe 其操作步骤是: --> 编写python程序 --> 再额外编写一个导入了 ...

  10. 利用opencv3中的kmeans实现抠图功能

    kmeans算法主要用来实现自动聚类,是一种非监督的机器学习算法,使用非常广泛.在opencv3.0中提供了这样一个函数,直接调用就能实现自动聚类,非常方便. 函数原型: C++: double km ...