最近学习了LinkCutTree,总结一下。

LinkCutTree是一种数据结构(是Tree Decomposition中的一种),她维护的一般是无向图(一个森林),支持连边、删边、链修改、链查询(点属于特殊的链,修改可以是单点修改、整链修改,查询可以是最值、和等)这四种操作。

中心思想是将边分类,一类边组成一些连续的链,每条链保存在一颗BST中(一般是Splay),BST中以点到根的距离为关键字(左边的点是右边的点的祖先),其它一些边连接这些链。(LinkCutTree是树链剖分(又叫轻重链剖分)的动态版本,并且更灵活),可以证明,LinkCutTree的各种操作都是均摊O(logn)的(渐进复杂度比树链剖分的O(log^2)还好,但是常数巨大,所以实测一般时间是树链剖分的1.5~2倍)。

上面的“链修改、链查询”指的是链上的点,如果要将对象改为边,可以为每条边建立一个边点,即若存在边(u,v),则新加一个点z代表边,将z连接u和v,z的点权就是(u,v)的边权,非边点的权设为-oo),然后对边权的统计就变成了对点权的统计(这是LCT中处理边信息的通法之一)。

 #include <cstdio>
#include <iostream>
#define maxn 10010
using namespace std; /*
我的代码风格:用数组模拟指针和结构体。
变量含义:
pnt[u] - path-parent of u in the tree
pre[u] - the father of u in the Splay
son[u][0] - the left child of u in the Splay
son[u][1] - the right child of u in the Splay
val[u] - the weight of u
sum[u] - the sum of weight of all the nodes in the subtree of u
siz[u] - the number of the nodes in the subtree of u
itg[u] - increasement tag ( the lazy tag )
rtg[u] - rotate tag ( the lazy tag )
*/
/*
模板功能:支持删边和连边,支持将一条链的点权做一个增量,支持查询一条链的点权和,判断两点是否再同一联通块中
因为是自己想的一个功能,所以没有地方交,不保证代码正确性。(重在理解)
代码中哪里不懂欢迎回复,代码丑别喷。
*/
namespace L {
int pnt[maxn], pre[maxn], son[maxn][], val[maxn],
sum[maxn], siz[maxn], itg[maxn], rtg[maxn]; void update( int nd ) {
sum[nd] = val[nd] + sum[son[nd][]] + sum[son[nd][]];
}
void rotate( int nd, int d ) {
int p = pre[nd];
int s = son[nd][!d];
int ss = son[s][d]; son[nd][!d] = ss;
son[s][d] = nd;
if( p ) son[p][ nd==son[p][] ] = s;
else pnt[s] = pnt[nd]; pre[nd] = s;
pre[s] = p;
pre[ss] = nd; update( nd );
update( s );
}
void pushdown( int nd ) {
if( rtg[nd] ) {
int &ls = son[nd][], &rs = son[nd][];
swap(ls,rs);
rtg[ls] ^= ;
rtg[rs] ^= ;
rtg[nd] = ;
}
if( itg[nd] ) {
int ls = son[nd][], rs = son[nd][];
int delta = itg[nd];
itg[ls] += delta;
itg[rs] += delta;
val[ls] += delta;
val[rs] += delta;
sum[ls] += siz[ls]*delta;
sum[rs] += siz[rs]*delta;
itg[nd] = ;
}
}
void big_push( int nd ) {
if( pre[nd] ) big_push(pre[nd]);
pushdown(nd);
}
void splay( int nd, int top= ) {
big_push(nd);
while( pre[nd]!=top ) {
int p = pre[nd];
int nl = nd==son[p][];
if( pre[p]==top ) {
rotate( p, nl );
} else {
int pp = pre[p];
int pl = p==son[pp][];
if( nl==pl ) {
rotate( pp, pl );
rotate( p, nl );
} else {
rotate( p, nl );
rotate( pp, pl );
}
}
}
}
void access( int nd ) {
int u = nd;
int v = ;
while( u ) {
splay( u );
int s = son[u][];
pre[s] = ;
pnt[s] = u;
pre[v] = u;
son[u][] = v;
update( u );
v = u;
u = pnt[u];
}
splay( nd );
}
int findroot( int nd ) {
while( pre[nd] ) nd=pre[nd];
while( pnt[nd] ) {
nd = pnt[nd];
while( pre[nd] ) nd=pre[nd];
}
return nd;
}
void makeroot( int nd ) {
access( nd );
rtg[nd] ^= ;
}
bool sameroot( int u, int v ) {
return findroot(u)==findroot(v);
}
void link( int u, int v ){
makeroot(u);
makeroot(v);
pnt[u] = v;
}
void cut( int u, int v ) {
makeroot(u);
access(v);
pnt[u] = ;
pre[u] = ;
son[v][] = ;
update( v );
}
void up_val( int u, int v, int delta ) {
makeroot(u);
access(v);
val[v] += delta;
sum[v] += siz[v]*delta;
itg[v] += delta;
}
int qu_sum( int u, int v ) {
makeroot(u);
access(v);
return val[v]+sum[son[v][]];
}
};
/*
int main() {
L::link(1,2);
L::link(2,3);
L::link(3,4);
L::up_val(1,3,3);
L::up_val(2,4,-3);
printf( "%d\n", L::qu_sum(1,1) );
printf( "%d\n", L::qu_sum(2,2) );
printf( "%d\n", L::qu_sum(3,3) );
printf( "%d\n", L::qu_sum(4,4) );
printf( "%d\n", L::qu_sum(2,3) );
}
*/
int main() {
L::link(,);
L::link(,);
L::link(,);
L::up_val( , , );
L::cut(,);
printf( "%d\n", L::qu_sum(,) );
printf( "%d\n", L::qu_sum(,) );
printf( "%d\n", L::sameroot(,) );
}

推荐学习资料:

杨思雨 《伸展树的基本操作与应用》

杨哲 《QTREE解法的一些研究》

http://blog.csdn.net/d891320478/article/details/9181385

LinkCutTree 总结的更多相关文章

  1. 【BZOJ-3779】重组病毒 LinkCutTree + 线段树 + DFS序

    3779: 重组病毒 Time Limit: 20 Sec  Memory Limit: 512 MBSubmit: 224  Solved: 95[Submit][Status][Discuss] ...

  2. BZOJ2049: [Sdoi2008]Cave 洞穴勘测 Link-Cut-Tree 模板题

    传送门 搞了这么长时间Splay终于可以搞LCT了,等等,什么是LCT? $LCT$就是$Link-Cut-Tree$,是维护动态树的一个很高效的数据结构,每次修改和查询的均摊复杂度为$O(logN) ...

  3. 【bzoj2049】[Sdoi2008]Cave 洞穴勘测 link-cut-tree

    2016-05-30  11:04:51 学习了link-cut-tree 二中神犇封禹的讲义感觉讲的超级清晰易懂啊(没有的可以q窝 算是模板吧 #include<bits/stdc++.h&g ...

  4. BZOJ-3282 Tree Link-Cut-Tree(似乎树链剖分亦可)

    蛋蛋用链剖A的,我写的LCT 3282: Tree Time Limit: 30 Sec Memory Limit: 512 MB Submit: 1241 Solved: 542 [Submit][ ...

  5. BZOJ-2049 Cave洞穴勘测 动态树Link-Cut-Tree (并查集骗分TAT)

    2049: [Sdoi2008]Cave 洞穴勘测 Time Limit: 10 Sec Memory Limit: 259 MB Submit: 5833 Solved: 2666 [Submit] ...

  6. 从ZOJ2114(Transportation Network)到Link-cut-tree(LCT)

    [热烈庆祝ZOJ回归] [首先声明:LCT≠动态树,前者是一种数据结构,而后者是一类问题,即:LCT—解决—>动态树] Link-cut-tree(下文统称LCT)是一种强大的数据结构,不仅可以 ...

  7. Link-Cut-Tree题目泛做(为了对应自己的课件)

    题目1:BZOJ 2049 洞穴勘测 #include <bits/stdc++.h> #define L(x) c[x][0] #define R(x) c[x][1] using na ...

  8. [Link-Cut-Tree]【学习笔记】

    可以按照<Utopiosphere>的调唱出来 “Link-Cut ,Time doesn’t stop .Prepare your doubts ,Eat them up” 参考资料: ...

  9. 算法笔记--Splay && Link-Cut-Tree

    Splay 参考:https://tiger0132.blog.luogu.org/slay-notes 普通模板: ; ], val[N], cnt[N], fa[N], sz[N], lazy[N ...

  10. Link-Cut-Tree详解

    图片参考YangZhe的论文,FlashHu大佬的博客 Link-Cut-Tree实际靠的是实链剖分,重链剖分和长链剖分珂以参考树链剖分详解 Link-Cut-Tree将某一个儿子的连边划分为实边,而 ...

随机推荐

  1. idea中tomcat乱码问题解决

    在idea中经常遇到jsp的乱码问题,原因是编码不是UTF-8的问题,这次来彻底解决idea的编码问题 首先设置idea编辑器的编码: File-Setting设置如下 然后配置tomcat的编码问题 ...

  2. Vue的keep-alive

    Vue的keep-alive: 简答的做下理解 缓存!页面从某一个页面跳转到另一个页面的时候,需要进行一定的缓存,然后这个时候调用的钩子函数是actived,而在第一次加载的时候,created.ac ...

  3. CDN基础详解

    什么是 CDN?     Origin Server: 源站,也就是做 CDN 之前的客户真正的服务器;   User: 访问者,也就是要访问网站的网民;   Edge Server: CDN 的服务 ...

  4. windows下面安装Python和pip教程

    第一步,先来安装Python.windows下面的Python安装一般是通过软件安装包安装而不是命令行,所以首先要在Python的官方主页上面下载最新的Python安装包.下载地址是:https:// ...

  5. java校验身份证号码

    /** * 18位身份证校验,粗略的校验 * @author lyl * @param idCard * @return */ public static boolean is18ByteIdCard ...

  6. Ubuntu 17.10 用 apt 搭建 lamp 环境、安装 phpmyadmin、redis 服务+扩展、mysql 扩展、开启错误提示、配置虚拟主机

    2018-02-24 13:50:30 更新: 个人喜欢相对原生又不太麻烦,所以用 apt 构建环境.不过,最近使用到现在记得出现过了 3 次 apache 或 mysql 服务器无法启动或无法连接的 ...

  7. 【转载】WebDriver(C#)之十点使用心得

    使用Selenium WebDriver驱动浏览器测试的过程中多多少少会遇到一些折腾人的问题,总结了一部分,做下分享. 一.隐藏元素处理(element not visible) 使用WebDrive ...

  8. ios 不支持iframe 解决方案

    在iframe外层在包一层,通过appendChild()把内容增加到容器中,完整代码如下: @section Css { <link href="@ViewHelper.Conten ...

  9. IP负载均衡技术

    参考链接:http://www.360doc.com/content/12/1117/19/820209_248442094.shtml

  10. (二)Spring 之IOC 详解

    第一节:spring ioc 简介 IOC(控制反转:Inversion of Control),又称作依赖注入dependency injection( DI ),是一种重要的面向对象编程的法则来削 ...