[模板] 动态树/LCT
简介
LCT是一种数据结构, 可以维护树的动态加边, 删边, 维护链上信息(满足结合律), 单次操作时间复杂度 \(O(\log n)\).(不会证)
思想类似树链剖分, 因为splay可以换根, 用splay维护重链, splay的中序遍历即为链按深度从小到大遍历的结果.
操作
注意区分splay和整棵树的区别, splay根和树根的区别.
\(Access(p)\) 操作指的是将p与根放在同一棵splay中.
\(MakeRoot(p)\) 操作指的是将p变为它所在树(而不是splay)的根. 由于维护的是链上信息, 这不会对答案产生影响.
\(FindRoot(p)\) 操作指的是求p所在树(而不是splay)的根.
\(Link(x,y)\) 操作指的是如果p与q不在同一棵树中, 那么连边 \((x,y)\).
\(Cut(x,y)\) 操作指的是如果p与q有边相连, 那么连边 \((x,y)\).
其中, 'p与q有边相连' 等价于同时满足:
- p,q在同一棵树中.
- p,q深度相差1.(splay中p,q中序遍历时相邻)
\(Split(x,y)\) 操作指的是取出 \((x,y)\) 这个链, 并放在一棵splay中.
具体实现见代码.
应用
- 动态树(代替树链剖分)
- 动态最小生成树
- 维护子树信息(AAA树)
- 维护并查集(e.g. 可持久化并查集)
- 优化dinic(据tarjan论文)(怕不是会写死)
Code
const int nsz=3e5+50;
int n,val[nsz];
struct tlct{
struct tnd{int ch[2],fa,sum,rv;}tree[nsz];
#define ls(p) tree[p].ch[0]
#define rs(p) tree[p].ch[1]
#define fa(p) tree[p].fa
#define dir(p) (rs(fa(p))==p)
bool isrt(int p){return ls(fa(p))!=p&&rs(fa(p))!=p;}//splay rt
void rev(int p){swap(ls(p),rs(p));tree[p].rv^=1;}
void pu(int p){
tree[p].sum=tree[ls(p)].sum^val[p]^tree[rs(p)].sum;
}
void pd(int p){
if(tree[p].rv==0)return;
if(ls(p))rev(ls(p));
if(rs(p))rev(rs(p));
tree[p].rv=0;
}
void pdt(int p){//push down whole splay; from top to bottom
if(!isrt(p))pdt(fa(p));
pd(p);
}
void rotate(int p){//fa(p) should exist
int x=fa(p),y=fa(x),dir1=dir(p),dir2=dir(x),z=tree[p].ch[dir1^1];
if(!isrt(x))tree[y].ch[dir2]=p;fa(p)=y;
tree[p].ch[dir1^1]=x;fa(x)=p;
tree[x].ch[dir1]=z;if(z)fa(z)=x;
pu(x),pu(p);//can't swap
}
void splay(int p){
pdt(p);
while(!isrt(p)){
if(!isrt(fa(p)))rotate(dir(p)==dir(fa(p))?fa(p):p);
rotate(p);
}
}
void access(int p){
for(int y=0;p;y=p,p=fa(p)){
splay(p),rs(p)=y;
pu(p);
}
}
void makert(int p){//p -> tree rt & splay rt
access(p),splay(p);
rev(p);
}
int findrt(int p){//find tree rt; p -> splay rt
access(p),splay(p);
while(ls(p))pd(p),p=ls(p);
splay(p); //不加会tle... 不知道为什么
return p;
}
bool iscon(int x,int y){return findrt(x)==findrt(y);}
void split(int x,int y){//x -> tree rt; y -> splay rt
makert(x);
access(y);
splay(y);
}
void link(int x,int y){
makert(x);
if(findrt(y)!=x)fa(x)=y;
}
void cut(int x,int y){
split(x,y);
if(fa(x)==y&&rs(x)==0)
fa(x)=ls(y)=0,pu(y);
}
void pr(){
rep(i,1,n)printf("nd=%d fa=%d ls=%d rs=%d sum=%d rv=%d\n",i,fa(i),ls(i),rs(i),tree[i].sum,tree[i].rv);
}
}lct;
//init
rep(i,1,n)tree[i].sum=val[i];
//query a chain
lct.split(b,c);
ans=lct.tree[c].sum;
//modify one point
lct.makert(b);
val[b]=c;
lct.pu(b);
[模板] 动态树/LCT的更多相关文章
- hdu 5002 (动态树lct)
Tree Time Limit: 16000/8000 MS (Java/Others) Memory Limit: 65536/65536 K (Java/Others)Total Submi ...
- hdu 5398 动态树LCT
GCD Tree Time Limit: 5000/2500 MS (Java/Others) Memory Limit: 65536/65536 K (Java/Others)Total Su ...
- bzoj2049-洞穴勘测(动态树lct模板题)
Description 辉辉热衷于洞穴勘测.某天,他按照地图来到了一片被标记为JSZX的洞穴群地区.经过初步勘测,辉辉发现这片区域由n个洞穴(分别编号为1到n)以及若干通道组成,并且每条通道连接了恰好 ...
- 动态树LCT(Link-cut-tree)总结+模板题+各种题目
一.理解LCT的工作原理 先看一道例题: 让你维护一棵给定的树,需要支持下面两种操作: Change x val: 令x点的点权变为val Query x y: 计算x,y之间的唯一的最短路径的点 ...
- 动态树LCT小结
最开始看动态树不知道找了多少资料,总感觉不能完全理解.但其实理解了就是那么一回事...动态树在某种意思上来说跟树链剖分很相似,都是为了解决序列问题,树链剖分由于树的形态是不变的,所以可以通过预处理节点 ...
- SPOJ OTOCI 动态树 LCT
SPOJ OTOCI 裸的动态树问题. 回顾一下我们对树的认识. 最初,它是一个连通的无向的无环的图,然后我们发现由一个根出发进行BFS 会出现层次分明的树状图形. 然后根据树的递归和层次性质,我们得 ...
- HDU 4718 The LCIS on the Tree (动态树LCT)
The LCIS on the Tree Time Limit: 6000/3000 MS (Java/Others) Memory Limit: 65535/65535 K (Java/Oth ...
- BZOJ 2002: [Hnoi2010]Bounce 弹飞绵羊 (动态树LCT)
2002: [Hnoi2010]Bounce 弹飞绵羊 Time Limit: 10 Sec Memory Limit: 259 MBSubmit: 2843 Solved: 1519[Submi ...
- HDU 5002 Tree(动态树LCT)(2014 ACM/ICPC Asia Regional Anshan Online)
Problem Description You are given a tree with N nodes which are numbered by integers 1..N. Each node ...
随机推荐
- 一文读懂HTTP/2及HTTP/3特性
摘要: 学习 HTTP/2 与 HTTP/3. 前言 HTTP/2 相比于 HTTP/1,可以说是大幅度提高了网页的性能,只需要升级到该协议就可以减少很多之前需要做的性能优化工作,当然兼容问题以及如何 ...
- 2019-02-18 扩展Python控制台实现中文反馈信息之二-正则替换
"中文编程"知乎专栏原文地址 续前文扩展Python控制台实现中文反馈信息, 实现了如下效果: >>> 学 Traceback (most recent call ...
- 谷歌AI涉足艺术、太空、外科手术,再强调AI七原则
谷歌AI涉足艺术.太空.外科手术,再强调AI七原则 https://mp.weixin.qq.com/s/MJG_SvKCEBKRvL3IWpL0bA 9月18日上午,Google在上海的2018世界 ...
- 《Flask Web开发》学习笔记
第一部分 Flask简介 前言:想熟练掌握一门web框架,为以后即将诞生的测试工具集做准备.为什么选择flask要做熟练掌握的一门框架,而不是其他的,最主要的原因是可以随意定制. 特别提醒:这本书的代 ...
- 【Linux】【Apatch Tomcat】Linux、CentOS7安装最新版Apartch Tomcat环境
1.前言 相当嫌弃,博客园搞掉了我快写完的 Tomcat. 请先安装 :[Linux][Java]CentOS7安装最新版Java1.8.191运行开发环境 虽然安装Tomcat没啥技术,但是还是记录 ...
- Hadoop Yarn框架详细解析
在说Hadoop Yarn之前,我们先来看看Yarn是怎样出现的.在古老的Hadoop1.0中,MapReduce的JobTracker负责了太多的工作,包括资源调度,管理众多的TaskTracker ...
- VS2015 IIS Express Web服务器无法启动解决办法
1.运行和调试vs2015项目 提示无法运行项目,打开vs2013项目发现可以正常运行,所以推测试vs2015项目配置有问题. 2.找到项目启动项中 .csproj文件,定位到<WebProje ...
- javascript Json和String互转
var jsonText = "{\"id\":\"123\",\"name\":\"tom\",\&qu ...
- CentOS7中利用Xshell6向虚拟机本地上传文件
环境交代 Linux系统:CentOS7, Xshell版本:6 操作步骤 下面我们以一个文件上传来演示用法 第一步 建立连接,这里不多说 在Xshell中点击如下图标,或者直接按 Alt+Ctrl+ ...
- SQLServer之触发器简介
触发器定义 触发器是数据库服务器中发生事件时自动执行的一种特殊存储过程.SQLServer允许为任何特定语句创建多个触发器.它的执行不是由程序调用,也不是手工启动,而是由事件来触发,当对数据库进行操作 ...