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

安利一个集训队讲解: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. 数据结构Java实现02----线性表与顺序表

    [声明] 欢迎转载,但请保留文章原始出处→_→ 生命壹号:http://www.cnblogs.com/smyhvae/ 文章来源:http://www.cnblogs.com/smyhvae/p/4 ...

  2. MySQL数据库学习笔记(一)----MySQL 5.6.21的安装和配置(setup版)

    [声明] 欢迎转载,但请保留文章原始出处→_→ 生命壹号:http://www.cnblogs.com/smyhvae/ 文章来源:http://www.cnblogs.com/smyhvae/p/4 ...

  3. Git 详解

    1. Git 1.1. Git是何方神圣? Git是用C语言开发的分布版本控制系统.版本控制系统可以保留一个文件集合的历史记录,并能回滚文件集合到另一个状态(历史记录状态).另一个状 态可以是不同的文 ...

  4. static,静态关键字的详解

    一,使用static声明属性 class Person{ // 定义Person类 String name ; // 定义name属性,暂时不封装 int age ; // 定义age属性,暂时不封装 ...

  5. Saltstack-自动化部署

    Saltstack概述 Salt一种全新的基础设施管理方式,部署轻松,在几分钟内可运行起来,扩展性好,很容易管理上万台服务器,速度够快,服务器之间秒级通讯. salt底层采用动态的连接总线, 使其可以 ...

  6. iOS程序间调用

    1.在被调用应用内的info.plist里面设置如下: 鼠标右击information property list ,然后从列表中选择URL types 右击 add row 添加一个对象(item) ...

  7. Maven 其他功能

    测试:指定测试哪些测试类,指定哪些测试类不测试,可以使用通配符 使用 Hudson 进行持续集成 持续集成:快速且高频率地自动构建项目的所有源码,并为项目成员提供丰富的反馈信息 一个典型的持续集成场景 ...

  8. POJ 3461 Oulipo

      E - Oulipo Time Limit:1000MS     Memory Limit:65536KB     64bit IO Format:%I64d & %I64u Submit ...

  9. 027医疗项目-模块二:药品目录的导入导出-导入功能的Action的编写

    前一篇文章我们写了Service层,这篇文章我们写一下Action层. 实现的功能: 1:我们先下载模板:然后按照模板里面的规则,插入数据.比如存在d盘. 2:然后浏览找到那个文件,上传上去. 然后把 ...

  10. 推荐一款开源的C#TCP通讯框架

    原来收费的TCP通讯框架开源了,这是一款国外的开源TCP通信框架,使用了一段时间,感觉不错,介绍给大家 框架名称是networkcomms 作者开发了5年多,目前已经停止开发,对于中小型的应用场景,够 ...