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

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

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

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

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操作:将之分离

(其实最开始想写指针的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、 最小生成树

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

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

#include<iostream>
#include<cstdio>
#include<algorithm>
#include<cstring>
#include<cmath>
using namespace std;
#define N 10010 int f[N],son[N][2],val[N],sum[N],tmp[N];bool rev[N];
bool isroot(int x)
{
return !f[x]||son[f[x]][0]!=x&&son[f[x]][1]!=x;
}//判根 void rev1(int x)
{
if(!x) return;
swap(son[x][0],son[x][1]);
rev[x]^=1;
}//翻转 void pb(int x)
{
if(rev[x])
rev1(son[x][0]),rev1(son[x][1]),rev[x]=0;
}//翻转 void up(int x)
{
sum[x]=val[x];
if(son[x][0])sum[x]+=sum[son[x][0]];
if(son[x][1])sum[x]+=sum[son[x][1]];
}//更新值 void rotate(int x)
{
int y=f[x],w=son[y][1]==x;
son[y][w]=son[x][w^1];
if(son[x][w^1]) f[son[x][w^1]]=y;
if(f[y])
{
int z=f[y];
if(son[z][0]==y)son[z][0]=x;
else if(son[z][1]==y)son[z][1]=x;
}
f[x]=f[y];f[y]=x;
son[x][w^1]=y;up(y);
}//旋转 void splay(int x)
{
int s=1,i=x,y;tmp[1]=i;
while(!isroot(i)) tmp[++s]=i=f[i];
while(s) pb(tmp[s--]);
while(!isroot(x))
{
y=f[x];
if(!isroot(y))
{
if((son[f[y]][0]==y)^(son[y][0]==x))
rotate(x); else rotate(y);
}
rotate(x);
}
up(x);
}//伸展 void access(int x)
{
for(int y=0;x;y=x,x=f[x])
splay(x),son[x][1]=y,up(x);
}//访问 int root(int x)
{
access(x);splay(x);
while(son[x][0]) x=son[x][0];
return x;
}//换根 void makeroot(int x)
{
access(x);
splay(x);
rev1(x);
} void link(int x,int y)
{
makeroot(x);
f[x]=y;
access(x);
} void cutf(int x)
{
access(x);
splay(x);
f[son[x][0]]=0;
son[x][0]=0;
up(x);
} void cut(int x,int y)
{
makeroot(x);
cutf(y);
}//分离 int ask(int x,int y)
{
makeroot(x);
access(y);
splay(y);
return sum[y];
}//查询值 int find(int x)
{
access(x);
splay(x);
int y=x;
while(son[y][0]) y=son[y][0];
return y;
}//判断连通性(类LCA) int main()
{ return 0;
}

学习笔记-动态树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. RMQ之ST算法模板

    #include<stdio.h> #include<string.h> #include<iostream> using namespace std; ; ],M ...

  2. SpringMVC系列之基本配置

    一.概述 Spring Web MVC是一种基于Java的实现了Web MVC设计模式的请求驱动类型的轻量级Web框架,即使用了MVC架构模式的思想,将web层进行职责解耦,基于请求驱动指的就是使用请 ...

  3. 墙国内新建Rails应用的要点(windows 7环境, Rails 4.2.0)

    1. 使用rails new 命令创建完的应用在自动执行bundle install不会成功,根据出错提示,判断原因有可能是被墙与https的证书的安全性问题. 作为开发环境,选用绕开的办法,在目录  ...

  4. [py]chr ord

    http://www.xuebuyuan.com/2067536.html 也可以help(ord)

  5. HighCharts 详细使用及API文档说明

    一.HighCharts开发说明: HighCharts开发实际上配置HighCharts每个部分,比如配置标题(title),副标题(subtitle)等,其中每个部分又有更细的参数配置,比如标题下 ...

  6. PagerIndicator主题样式修改

    默认的黑色好丑 所以大家需要动手改造一下, 1 打开 Manifest.xml <activity android:name="com.zb.zhihuianyang.MainActi ...

  7. Java 通过JDBC查询数据库表结构(字段名称,类型,长度等)

    Java 通过JDBC查询数据库表结构(字段名称,类型,长度等) 发布者:唛唛家的豆子   时间:2012-11-20 17:54:02   Java 通过JDBC查询数据库表结构(字段名称,类型,长 ...

  8. matlab矩阵合并及相关运算

    1.matlab允许向量(和矩阵)合并,且matlab提供了两种合并方式,[a,b]和[a;b],两者的结果是不一样的. a=rand(2,3): b=rand(2,3): c=[a;b]: d=[a ...

  9. 几种Java NIO框架的比较(zz)

    问题:生活中工作中,会有人问我javaNIO框架里面 Netty Mina  xSocket Grizzly 等等哪个比较好? 在这里写一下自己的感受,也算是总结一下吧 在我的印象中.不管是什么NIO ...

  10. 系统级I/O

    Unix I/O 输入操作是从I/O设备拷贝数据到主存,而输出操作是从主存拷贝数据到I/O设备. 一个文件就是一个字节序列. 所有的I/O设备,如网络.磁盘.和终端,都被模型化为文件,而所有的输入和输 ...