[模板] 动态树/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 ...
随机推荐
- SAP MM盘点流程里如何处理事务代码MI11 Recount过的盘点凭证?
SAP MM盘点流程里如何处理事务代码MI11 Recount过的盘点凭证? 1, MI01 create a physical inventory document, 2, MI04 to inpu ...
- Mapbox浅析(快速入门Mapbox)
1.是什么? Mapbox是一个可以免费创建并定制个性化地图的网站. 2.了解一些基本东西 常见的 mapbox.js和mapbox-gl.js的异同点? 相同点: 1.都是由Mapbox公司推出的免 ...
- Apex 单元测试辅助函数简介
startTest和stopTest的使用 在Apex的Test类中,有startTest和stopTest两个函数.这两个函数经常配对使用. 每个单元测试函数都只能调用它们一次. startTest ...
- XPath Helper的安装与使用
摘要 : XPath Helper可以支持在网页点击元素生成xpath,整个抓取使用了xpath.正则表达式.消息中间件.多线程调度框架的chrome插件. xpath:是一门XML和HTML文档中查 ...
- Istio入门实战与架构原理——使用Docker Compose搭建Service Mesh
本文将介绍如何使用Docker Compose搭建Istio.Istio号称支持多种平台(不仅仅Kubernetes).然而,官网上非基于Kubernetes的教程仿佛不是亲儿子,写得非常随便,不仅缺 ...
- 伙伴系统之伙伴系统概述--Linux内存管理(十五)
在内核初始化完成之后, 内存管理的责任就由伙伴系统来承担. 伙伴系统基于一种相对简单然而令人吃惊的强大算法. Linux内核使用二进制伙伴算法来管理和分配物理内存页面, 该算法由Knowlton设计, ...
- c/c++ socket API 调用后的错误判断 perror errno
socket API 调用后的错误判断 perror errno 调用完socket API后,需要判断调用是否成功与失败.如果失败,会自动设置errno(是个整数), 并且用perror可以打印出具 ...
- Linux学习历程——Centos 7 touch命令
一.命令介绍 touch 命令用于创建空白文件,以及设置文件的时间. ----------------------------------------------------------------- ...
- phpstorm设置编码格式
phpstorm设置编码格式 默认: utf-8格式 设置方法: file -> settings -> Editor -> file encodng -> project e ...
- 利用java实现excel转pdf文件
在有些需求当中我们需要抓取字段并且填充到excel表格里面,最后将excel表格转换成pdf格式进行输出,我第一次接触这个需求时,碰到几个比较棘手的问题,现在一一列出并且提供解决方案. 1:excel ...