LinkCutTree 总结
最近学习了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 总结的更多相关文章
- 【BZOJ-3779】重组病毒 LinkCutTree + 线段树 + DFS序
3779: 重组病毒 Time Limit: 20 Sec Memory Limit: 512 MBSubmit: 224 Solved: 95[Submit][Status][Discuss] ...
- BZOJ2049: [Sdoi2008]Cave 洞穴勘测 Link-Cut-Tree 模板题
传送门 搞了这么长时间Splay终于可以搞LCT了,等等,什么是LCT? $LCT$就是$Link-Cut-Tree$,是维护动态树的一个很高效的数据结构,每次修改和查询的均摊复杂度为$O(logN) ...
- 【bzoj2049】[Sdoi2008]Cave 洞穴勘测 link-cut-tree
2016-05-30 11:04:51 学习了link-cut-tree 二中神犇封禹的讲义感觉讲的超级清晰易懂啊(没有的可以q窝 算是模板吧 #include<bits/stdc++.h&g ...
- BZOJ-3282 Tree Link-Cut-Tree(似乎树链剖分亦可)
蛋蛋用链剖A的,我写的LCT 3282: Tree Time Limit: 30 Sec Memory Limit: 512 MB Submit: 1241 Solved: 542 [Submit][ ...
- BZOJ-2049 Cave洞穴勘测 动态树Link-Cut-Tree (并查集骗分TAT)
2049: [Sdoi2008]Cave 洞穴勘测 Time Limit: 10 Sec Memory Limit: 259 MB Submit: 5833 Solved: 2666 [Submit] ...
- 从ZOJ2114(Transportation Network)到Link-cut-tree(LCT)
[热烈庆祝ZOJ回归] [首先声明:LCT≠动态树,前者是一种数据结构,而后者是一类问题,即:LCT—解决—>动态树] Link-cut-tree(下文统称LCT)是一种强大的数据结构,不仅可以 ...
- Link-Cut-Tree题目泛做(为了对应自己的课件)
题目1:BZOJ 2049 洞穴勘测 #include <bits/stdc++.h> #define L(x) c[x][0] #define R(x) c[x][1] using na ...
- [Link-Cut-Tree]【学习笔记】
可以按照<Utopiosphere>的调唱出来 “Link-Cut ,Time doesn’t stop .Prepare your doubts ,Eat them up” 参考资料: ...
- 算法笔记--Splay && Link-Cut-Tree
Splay 参考:https://tiger0132.blog.luogu.org/slay-notes 普通模板: ; ], val[N], cnt[N], fa[N], sz[N], lazy[N ...
- Link-Cut-Tree详解
图片参考YangZhe的论文,FlashHu大佬的博客 Link-Cut-Tree实际靠的是实链剖分,重链剖分和长链剖分珂以参考树链剖分详解 Link-Cut-Tree将某一个儿子的连边划分为实边,而 ...
随机推荐
- B - GuGuFishtion(莫比乌斯 欧拉函数 预处理mu函数的欧拉函数的模板)
题目链接:https://cn.vjudge.net/contest/270608#problem/B 题目大意:题目中说,就是对欧拉函数的重新定义的一种函数的求和. 证明方法: AC代码: #inc ...
- 15 - reduce-pratial偏函数-lsu_cache
目录 介绍 1 reduce方法 2 partial方法(偏函数) 2.1 partial方法基本使用 2.2 partial原码分析 2.3 functools.warps实现分析 3 lsu_ca ...
- DAY1-GO初识(概述)
一.概述 1.特征 1.1.语法简单:规则严谨.保留指针.但默认阻止指针运算.将切片和字典作为内置类型.更好的维护性: 1.2.并发模型:运行时用GOroutine,一个关键字.简单而自然:搭配cha ...
- 64_n3
nodejs-yamlish-0.0.5-9.fc26.noarch.rpm 11-Feb-2017 16:48 11966 nodejs-yargs-3.2.1-6.fc26.noarch.rpm ...
- MySQL JDBC驱动下载
下载地址:https://pan.baidu.com/s/1VLNaV_rz2P1jMtYrjJydiQ
- 动手编写TCP服务器系列之一:日志文件
前言 在几个月之前,笔者想自己实现一个性能比较良好的基于tcp的服务器.于是断断续续写了个把月,因为还需要找工,还有论文什么的.拖了这么久.现在开辟这样的一个博客,我想记录下自己的思路,也和大家分享自 ...
- (三)Spring 之AOP 详解
第一节:AOP 简介 AOP 简介:百度百科: 面向切面编程(也叫面向方面编程):Aspect Oriented Programming(AOP),是软件开发中的一个热点,也是Spring框架中的一个 ...
- CentOS/RHEL Linux安装EPEL第三方软件源
https://www.vpser.net/manage/centos-rhel-linux-third-party-source-epel.html
- Characters_of_the_Three_Kingdoms - 三国人物结构化数据
Characters_of_the_Three_Kingdoms - 三国人物结构化数据 三国人物结构化数据 为什么会有这个项目 需求1:摆脱网上那些长篇累牍的文章: 需求2:只是想简单查看下人物姓甚 ...
- Python 中for...esle和while...else语法
Python的for...else和while...else语法,这是Python中最不常用,最为误解的语法特性之一. Python中的for.while循环都有一个可选的else分支(类似if语句和 ...