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将某一个儿子的连边划分为实边,而 ...
随机推荐
- Struts结果跳转方式(四种result配置)
1.转发(默认转发)
- django框架<三>
一.ORM操作 1.django orm创建数据库的方法 (1)指定连接pymysql(python3.x),先配置__init__.py import pymysql pymysql.instal ...
- window server 2008 配置ftp并实现用户隔离
文件传输协议(FTP)是一个标准的网络协议,用于传输计算机文件从一台主机到另一台主机通过TCP为基础的网络,如互联网. -WIKI百科 好久没更新教程了, 今天更新一下博客,也不知道会不会有人看….本 ...
- oracle只要第一条数据SQL
select * from ( select * from COMMON_BIZREL_WF where sponsor is not null order by serialid ) where r ...
- ps的各种参数
1.CPU占用最多的前10个进程: ps auxw|head -1;ps auxw|sort -rn -k3|head -10 2.内存消耗最多的前10个进程 ps auxw|head -1;ps a ...
- JS函数学习
=============数学函数========== 1.Math.random()为取随机数0~1之间的:0可以取到,1取不到 alert(Math.random()); 2.Math.PI为3. ...
- day3 文件操作
文件操作是在内存中进行操作的,因为文件是存储在内存中的. open函数,该函数用于文件处理: 操作文件时,一般需要经历如下步骤: (1)打开文件: (2)操作文件 一.打开文件 文件句柄 = open ...
- Docker Zero Deployment and Secrets (一)
在本节中,主要介绍在Docker swarm中如何不中断应用高可靠性的情况下更新服务和stack.这也叫做zero downtime deployment.还有就是swam如何管理密钥,保证容器之间的 ...
- Java中的覆盖和隐藏以及final关键字
Java覆盖和隐藏 (1) 变量只能被隐藏(包括静态和非静态),不能被覆盖: (2) 可以用子类的静态变量隐藏父类的静态变量,也可以用子类的非静态变量隐藏父类的静态变量,也可以用非最终变量(final ...
- 【C++】指针的引用及面向对象
指针的引用 #include <iostream> using namespace std; struct Teacher { ]; int age; }; int getTeacher( ...