树上数据结构——LCT
树上数据结构——LCT
概述
LCT是一种强力的树上数据结构,支持以下操作:
- 链上求和
- 链上求最值
- 链上修改
- 子树修改
- 子树求和
- 换根
- 断开树上一条边
- 连接两个点,保证连接后仍然是一棵树。
基本概念
LCT是对树的实链剖分,即把所有边划分为实边和虚边
类似于重链剖分,每个点连向子节点中的实链至多只会有一条,把这条实边连向的儿子叫做实儿子
把一些实边连接的点构成的链叫做实链,容易发现实链之间没有共同点
需要注意的是一个不在实边上的点(一些叶节点)也视为一条没有实边的实链
于是实链之间一定是用虚边链接的
要涉及动态删连边操作,于是使用splay来维护一条实链,splay是LCT的辅助树
此处splay的深度按中序遍历严格递增
由于用splay维护,LCT的实边是动态的,可以改变
核心操作
access(x):让x到根节点的所有边均为实边,并且x没有实儿子
这个推荐flash_hu的博客,简单易懂
稍微说一下,每次操作先把当前要连的点splay到当前splay的根,由于splay中深度按中序遍历递增,此时根的右儿子一定是之前连的实链,需要去掉
于是把之前的点连到当前根的右儿子就行了
注意此时一些\(fa,son,isroot\)之类的信息改变了,需要\(push\)_\(up\)
void access(int x){
for(int y=0;x;y=x,x=fa[x]){ //y是之前的根,x是当前需要连的点
splay(x); ch[x][1]=y;
push_up(x);
}
}
其他操作
makeroot
换根操作
access(x)之后x是深度最大的点
所以splay(x)之后,x在splay中一定没有右子树,这个时候翻转整个splay,所有点的深度就都倒过来了,x成为深度最小的点,即为根节点
void pushr(int x){
swap(ch[x][0],ch[x][1]);
r[x]^=1;
}
void makeroot(int x){
access(x); splay(x);
pushr(x);
}
findroot
找所在树的树根,可以用来判断两点之间的连通性(两点所在树相同则有唯一相同根
int findroot(int x){
access(x);splay(x);
while(c[x][0]) push_down(x),x=ch[x][0];//寻找深度最小的点,此处push_down是为了x到跟的标记放完,好判连通性
splay(x);//多多splay有益健康
return 0;
}
split
把一条路径拉成一个splay
void spilt(int x,int y){
makeroot(x);access(y);
splay(y);
}
link
连一条边,保证连完还是一棵树
不保证合法:
int link(int x,int y){
makeroot(x);
if(findroot(y)==x) return 0;
fa[x]=y; //把x作为y的儿子
return 1;
}
保证合法:
void link(int x,int y){
makeroot(x);
fa[x]=y;
}
此处连的边是虚边(感受到实链剖分的方便了罢
cut
断边
保证存在:
void cut(int x,int y){
split(x,y);
fa[x]=ch[y][0]=0; }
不存在此边的时候是什么情况呢?
先把x给\(makeroot\)到根
x和y不连通 (\(findroot\))
在同一splay中而没有直接连边 (\(f[y]==x\)且\(!c[y][0]\))
(考虑其他的点在哪里,在findroot之后x到了根节点,如果x和y之间有点,只能是在y到根的路径上或者y的左儿子上)
int cut(int x,int y){
makeroot(x);
if(findroot(y)!=x||fa[y]!=x||ch[y][0]) return 0;
fa[y]=ch[x][1]=0;
push_up(x);
return 1;
}
nroot
naiive的操作,判断此点是否不是当前splay的根节点
int nroot(int x){
return (ch[fa[x]][1]==x||ch[fa[x]][0]==x);
}
splay 的特殊性
此处splay的标记一定要从上往下放,也就是先开个栈把标记放完再旋转
完整模板
#include<iostream>
#include<algorithm>
#include<cstdio>
#include<cstring>
using namespace std;
#define reg register int
#define il inline
#define ls ch[x][0]
#define rs ch[x][1]
int read(){
int x=0,pos=1;char ch=getchar();
for(;!isdigit(ch);ch=getchar()) if(ch=='-') pos=0;
for(;isdigit(ch);ch=getchar()) x=(x<<1)+(x<<3)+ch-'0';
return pos?x:-x;
}
const int N = 400025;
int fa[N],ch[N][2],v[N],s[N],st[N],r[N];
il int nroot(int x){
return ch[fa[x]][1]==x||ch[fa[x]][0]==x;
}
il int get(int x){
return ch[fa[x]][1]==x;
}
il void push_up(int x){
s[x]=v[x]^s[ls]^s[rs];
}
il void pushr(int x){
swap(ls,rs);r[x]^=1;
}
il void push_down(int x){
if(r[x]){
if(ls) pushr(ls);
if(rs) pushr(rs);
r[x]=0;
}
}
il void rotate(int x){
int f=fa[x],g=fa[f],kx=get(x),kf=get(f);
if(nroot(f)) ch[g][kf]=x;
fa[x]=g;
/*if(ch[x][kx^1])*/ fa[ch[x][kx^1]]=f;
ch[f][kx]=ch[x][kx^1];
fa[f]=x;ch[x][kx^1]=f;
push_up(f);push_up(x);
}
il void push(int x){
if(nroot(x)) push(fa[x]);
push_down(x);
}
il void splay(int x){
int f,g;
push(x);//fuctional stack
while(nroot(x)){
f=fa[x],g=fa[f];
if(nroot(f)){
rotate(get(x)==get(f)?f:x);
}
rotate(x);
}
}
il void access(int x){
for(reg y=0;x;y=x,x=fa[x]){
splay(x);rs=y;push_up(x);
}
}
il void makeroot(int x){
access(x);splay(x);pushr(x);
}
il void spilt(int x,int y){
makeroot(x);
access(y);splay(y);
}
il int findroot(int x){
access(x);splay(x);
while(ls) x=ls;
splay(x);
return x;
}
il void link(int x,int y){
makeroot(x);
if(findroot(y)!=x) fa[x]=y;
}
il void cut(int x,int y){
makeroot(x);
if(findroot(y)==x&&fa[y]==x&&!ch[y][0]){
fa[y]=ch[x][1]=0;
push_up(x);
}
}
int n,m;
int main(){
n=read();m=read();
for(reg i=1;i<=n;i++){
v[i]=read();
}
for(reg i=1;i<=m;++i){
int opt=read(),x=read(),y=read();
if(opt==0){
spilt(x,y);printf("%d\n",s[y]);
}else if(opt==1){
link(x,y);
}else if(opt==2) cut(x,y);
else splay(x),v[x]=y;
}
return 0;
}
之后可能会补自己做的LCT题(咕
在创作本文的过程中,参考了以下文章:
- [flash_hu大佬的博客][https://www.cnblogs.com/flashhu/p/8324551.html]
- [NOI级别的超强数据结构——Link-cut-tree(动态树)学习小记][https://blog.csdn.net/qq_36551189/article/details/79152612]
- 成都七中的LCT课件(有一点吧
- Yang Zhe 2007年的论文
树上数据结构——LCT的更多相关文章
- 2019暑期金华集训 Day5 树上数据结构
自闭集训 Day5 树上数据结构 前置知识 点分治 边分治 树链剖分 LCT Top Tree LCT时间复杂度 线段树每次查询是严格\(\log n\)的,然而splay维护连续段的时候,如果每次查 ...
- 模板—数据结构—LCT
模板—数据结构—LCT Code: #include <cstdio> #include <algorithm> using namespace std; #define N ...
- ZROI 19.08.01 树上数据结构
1.总览 LCT 链分治(树剖) 点/边分治 2.点分治 一棵树,点有\(0/1\),多次修改,询问最远的两个\(1\)距离. 建出点分树,每个子树用堆维护:①最远的\(1\)距离:②它的每个儿子的① ...
- ZROI 暑期高端峰会 A班 Day4 树上数据结构
FBI Warning:本文含有大量人类的本质之一. 你经历过绝望吗? [ZJOI2007]捉迷藏 询问树上最远黑点对. 动态边分治可以比点分治少一个 \(\log\). bzoj3730 咕了. [ ...
- CF1111E Tree 动态规划+LCT
这个题的思路非常好啊. 我们可以把 $k$ 个点拿出来,那么就是求将 $k$ 个点划分成不大于 $m$ 个集合的方案数. 令 $f[i][j]$ 表示将前 $i$ 个点划分到 $j$ 个集合中的方案数 ...
- OI题目类型总结整理
## 本蒟蒻的小整理qwq--持续更新(咕咕咕) 数据结构 数据结构 知识点梳理 数据结构--线段树 推荐yyb dalao的总结--戳我 以后维护线段树还是把l,r写到struct里面吧,也别写le ...
- zhengrui集训D1-D5笔记
Day_1 计数 它咕掉了 Day_1 序列数据结构 它咕掉了 Day_2 线性代数 高斯消元\Large{高斯消元}高斯消元 普通版:略 模质数:求逆 模合数:exgcd 逆矩阵\Large{逆矩阵 ...
- 【BZOJ-2555】SubString 后缀自动机 + LinkCutTree
2555: SubString Time Limit: 30 Sec Memory Limit: 512 MBSubmit: 1936 Solved: 551[Submit][Status][Di ...
- The Last Week
二轮省选前的最后一周了呢. 一路走到这里,真的很希望能继续走下去. 好好调整一下状态,争取能有机会买D吧(虽然现在似乎D也没什么用了 day1 多项式 多项式ln 多项式exp day2 数据结构 L ...
随机推荐
- [python]文档字符串
文档字符串可以在运行时访问,也可以用来自动生成文档. 输入: def foo(): print "This is a doc string" return True foo() 运 ...
- bzoj 1146 网络管理Network (CDQ 整体二分 + 树刨)
题目传送门 题意:求树上路径可修改的第k大值是多少. 题解:CDQ整体二分+树刨. 每一个位置上的数都会有一段持续区间 根据CDQ拆的思维,可以将这个数拆成出现的时间点和消失的时间点. 然后通过整体二 ...
- codeforces D. Mahmoud and Ehab and the binary string(二分)
题目链接:http://codeforces.com/contest/862/submission/30696399 题解:这题一看操作数就知道是二分答案了.然后就是怎么个二分法,有两种思路第一种是找 ...
- HDFS 读写流程-译
HDFS 文件读取流程 Client 端调用 DistributedFileSystem 对象的 open() 方法. 由 DistributedFileSystem 通过 RPC 向 NameNod ...
- CSS3 03. 3D变换、坐标系、透视perspective、transformZ、transform-style添加3D效果、backface-visibility元素背面可见、动画animation、@keyfarmes、多列布局
1.左手坐标系 伸出左手,让拇指和食指成“L”形,大拇指向右,食指向上,中指指向前方.这样我们就建立了一个左手坐标系,拇指.食指和中指分别代表X.Y.Z轴的正方向.如下图 CSS中的3D坐标系 CSS ...
- SVN中忘记上传自己写的工程,但是IP已经变了的解决方案
苦于自己没有养成每天下班上传SVN的好习惯,第二天来又发现IP变了,只得把自己写的删掉,记录一下解决方法: 第一个红框中的svn://192.168.0.103/FH是前一天的IP链接地址,结果发现今 ...
- iOS代码混淆
混淆原理 代码编译阶段将符号(方法名.属性名等)替换成随机生成的字符串 长话短说,直接上步骤. 混淆集成步骤 步骤一.创建shell文件(confuse.sh)并配置相应的运行环境. 在项目根目录下新 ...
- 洛谷 P1219八皇后
把全部,在这251秒,赌上! ——<游戏人生zero> 题目:https://www.luogu.org/problem/P1219 八皇后是一道非常非常非常经典的深搜+回溯的题目. 这道 ...
- MySQL-注释-Navicat基本使用-复杂查询练习题-解题思路-pymysql操作数据库-SQL注入-05
目录 mysql语句注释 navicat 的基本使用 特色(个人总结) 与数据服务器建立连接 创建&打开数据库.表 创建 打开 修改操作表结构 修改表结构 查询修改操作表数据 基本语句对应的操 ...
- Winform中设置ZedGraph曲线图的字体样式是避免出现边框
场景 Winforn中设置ZedGraph曲线图的属性.坐标轴属性.刻度属性: https://blog.csdn.net/BADAO_LIUMANG_QIZHI/article/details/10 ...