学习笔记-动态树Link-Cut-Tree
--少年你有梦想吗?
--少年你听说过安利吗?
安利一个集训队讲解: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的更多相关文章
- 动态树(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) ...
- 【学习笔记】LCT link cut tree
大概就是供自己复习的吧 1. 细节讲解 安利两篇blog: Menci 非常好的讲解与题单 2.模板 把 $ rev $ 和 $ pushdown $ 的位置记清 #define lc son[x][ ...
- LCT总结——概念篇+洛谷P3690[模板]Link Cut Tree(动态树)(LCT,Splay)
为了优化体验(其实是强迫症),蒟蒻把总结拆成了两篇,方便不同学习阶段的Dalao们切换. LCT总结--应用篇戳这里 概念.性质简述 首先介绍一下链剖分的概念(感谢laofu的讲课) 链剖分,是指一类 ...
- Link Cut Tree学习笔记
从这里开始 动态树问题和Link Cut Tree 一些定义 access操作 换根操作 link和cut操作 时间复杂度证明 Link Cut Tree维护链上信息 Link Cut Tree维护子 ...
- P3690 【模板】Link Cut Tree (动态树)
P3690 [模板]Link Cut Tree (动态树) 认父不认子的lct 注意:不 要 把 $fa[x]$和$nrt(x)$ 混 在 一 起 ! #include<cstdio> v ...
- 【刷题】洛谷 P3690 【模板】Link Cut Tree (动态树)
题目背景 动态树 题目描述 给定n个点以及每个点的权值,要你处理接下来的m个操作.操作有4种.操作从0到3编号.点从1到n编号. 0:后接两个整数(x,y),代表询问从x到y的路径上的点的权值的xor ...
- LuoguP3690 【模板】Link Cut Tree (动态树) LCT模板
P3690 [模板]Link Cut Tree (动态树) 题目背景 动态树 题目描述 给定n个点以及每个点的权值,要你处理接下来的m个操作.操作有4种.操作从0到3编号.点从1到n编号. 0:后接两 ...
- 学习笔记:Link Cut Tree
模板题 原理 类似树链剖分对重儿子/长儿子剖分,Link Cut Tree 也做的是类似的链剖分. 每个节点选出 \(0 / 1\) 个儿子作为实儿子,剩下是虚儿子.对应的边是实边/虚边,虚实时可以进 ...
- LG3690 【模板】Link Cut Tree (动态树)
题意 给定n个点以及每个点的权值,要你处理接下来的m个操作.操作有4种.操作从0到3编号.点从1到n编号. 0:后接两个整数(x,y),代表询问从x到y的路径上的点的权值的xor和.保证x到y是联通的 ...
随机推荐
- Linux下安装使用NMON监控、分析系统性能
背景:今天在LoadRunner11.0中使用rstat监控linux过程中,始终提示如下错: Monitor name :UNIX Resources. Cannot initialize the ...
- http协议详解<一>
原创作品,允许转载,转载时请务必以超链接形式标明文章 原始出处 .作者信息和本声明.否则将追究法律责任.http://7826443.blog.51cto.com/7816443/1729227 写在 ...
- WPF - MVVM - 如何将ComboBox的Selectchange事件binding到ViewModel
转:http://www.cnblogs.com/mantian/p/3713524.html 将所有的事件,属性,都映射到ViewModel中.好处多多,以后开发尽量用这种模式. 解决方法: 使用S ...
- C++ Set & MultiSet
转自http://www.cppblog.com/wanghaiguang/archive/2012/06/05/177627.html STL Set介绍集合(Set)是一种包含已排序对象的关联容器 ...
- C语言 读取文件中特定数据
//读取文件数据 #define _CRT_SECURE_NO_WARNINGS #include<stdio.h> #include<stdlib.h> struct jia ...
- C++哈弗曼编码
// haffman.cpp : 定义控制台应用程序的入口点. // #include "stdafx.h" #include<iostream> using name ...
- php基础05:常量
<?php // 1.PHP 常量介绍 // 常量是单个值的标识符(名称).在脚本中无法改变该值.有效的常量名以字符或下划线开头(常量名称前面没有 $ 符号). // 2设置 PHP 常量 // ...
- python数字图像处理(8):对比度与亮度调整
图像亮度与对比度的调整,是放在skimage包的exposure模块里面 1.gamma调整 原理:I=Ig 对原图像的像素,进行幂运算,得到新的像素值.公式中的g就是gamma值. 如果gamma& ...
- Caffe学习系列(5):其它常用层及参数
本文讲解一些其它的常用层,包括:softmax_loss层,Inner Product层,accuracy层,reshape层和dropout层及其它们的参数配置. 1.softmax-loss so ...
- Viewpager模仿微信主布局的三种方式 ViewPager,Fragment,ViewPager+FragmentPagerAdapter
效果大概就是这样 很简单 : 1 创建 top 和bottom 2主界面布局 添加top 和bottom 中间添加一个ViewPage 3 给ViewPager 和 底部View设置点击事件 源码下载 ...