LUOGU P3690 【模板】Link Cut Tree (lct)
解题思路
\(lct\)就是基于实链剖分,用\(splay\)来维护每一条实链,\(lct\)的维护对象是一棵森林。\(lct\)支持很多神奇的操作:
\(1、\) \(access\):这是\(lct\)的核心操作,就是将一个点与根打通,就是把路径上的所有边变成实边,具体就是转到根,换儿子,更新信息。
\(2、\)\(makeroot\):将指定点作为原树的根,就是先\(access\)后,\(x\)一定是深度最大的点,再\(splay\) \(x\) 后将\(x\)的儿子进行翻转,这样就可以使\(x\)变为深度最小的节点,即为根。
\(3、\)\(findroot\) :判断两点是否联通,就是先\(access\)后,\(splay\) \(x\),然后这样的话\(x\)就一定只有左儿子,因为\(x\)是深度最深的点,然后一直跳左儿子即可。
\(4、\)\(split\) :访问\(x\)到\(y\)这条链,就是先\(makeroot\) \(x\),让\(x\)变为根,再\(access\) \(y\)把\(y\)与\(x\)打通,最后把\(y\)转上去就行了。
\(5、\)\(link\):连边,就是把其中一个点\(makeroot\),然后直接连一条虚边。
\(6、\) \(cut\):断边,先把\(x\)与\(y\)的路径拿出来,就是\(split\)操作,然后要判断一下\(y\)的左儿子是否为\(x\),还要判断一下\(x\)是否有右儿子。
剩下的一些操作跟\(splay\)比较像。
代码
#include<iostream>
#include<cstdio>
#include<cstring>
#include<cmath>
#include<cstdlib>
using namespace std;
const int MAXN = 300005;
inline int rd(){
int x=0,f=1;char ch=getchar();
while(!isdigit(ch)) {f=ch=='-'?0:1;ch=getchar();}
while(isdigit(ch)) {x=(x<<1)+(x<<3)+ch-'0';ch=getchar();}
return f?x:-x;
}
int n,m,w[MAXN];
int fa[MAXN],sum[MAXN],ch[MAXN][2];
bool tag[MAXN];
inline bool check(int x){
return (x==ch[fa[x]][1]);
}
inline bool isroot(int x){
return (ch[fa[x]][0]!=x && ch[fa[x]][1]!=x);
}
inline void pushup(int x){
sum[x]=sum[ch[x][0]]^sum[ch[x][1]]^w[x];
}
inline void pushdown(int x){
if(tag[x]){
if(ch[x][0]) tag[ch[x][0]]^=1,swap(ch[ch[x][0]][0],ch[ch[x][0]][1]);
if(ch[x][1]) tag[ch[x][1]]^=1,swap(ch[ch[x][1]][0],ch[ch[x][1]][1]);
tag[x]=0;
}
}
inline void update(int x){
if(!isroot(x)) update(fa[x]);pushdown(x);
}
inline void rotate(int x){
int y=fa[x],z=fa[y];bool chk=check(x);
if(!isroot(y)) ch[z][(y==ch[z][1])]=x;
ch[y][chk]=ch[x][chk^1];fa[ch[x][chk^1]]=y;
fa[y]=x;fa[x]=z;ch[x][chk^1]=y;
pushup(y);pushup(x);
}
inline void splay(int x){
update(x);
for(;!isroot(x);rotate(x))
if(!isroot(fa[x])) rotate(check(x)==check(fa[x])?fa[x]:x);
}
inline void access(int x){
for(int y=0;x;y=x,x=fa[x])
splay(x),ch[x][1]=y,pushup(x);
}
inline void makeroot(int x){
access(x);splay(x);
tag[x]^=1;swap(ch[x][0],ch[x][1]);
}
inline int findroot(int x){
access(x);splay(x);
while(ch[x][0]) pushdown(x),x=ch[x][0];
return x;
}
inline void split(int x,int y){
makeroot(x);access(y);splay(y);
}
inline void link(int x,int y){
if(findroot(x)==findroot(y)) return;
makeroot(x);fa[x]=y;
}
inline void cut(int x,int y){
if(findroot(x)!=findroot(y)) return;
split(x,y);if(ch[y][0]==x && !ch[x][1]) fa[x]=0,ch[y][0]=0,pushup(y);
}
int main(){
n=rd(),m=rd();int op,x,y;
for(int i=1;i<=n;i++) w[i]=rd();
while(m--){
op=rd(),x=rd(),y=rd();
if(op==0) {split(x,y);printf("%d\n",sum[y]);}
if(op==1) link(x,y);
if(op==2) cut(x,y);
if(op==3) splay(x),w[x]=y;
}
return 0;
}
LUOGU P3690 【模板】Link Cut Tree (lct)的更多相关文章
- 洛谷P3690 [模板] Link Cut Tree [LCT]
题目传送门 Link Cut Tree 题目背景 动态树 题目描述 给定n个点以及每个点的权值,要你处理接下来的m个操作.操作有4种.操作从0到3编号.点从1到n编号. 0:后接两个整数(x,y),代 ...
- LCT总结——概念篇+洛谷P3690[模板]Link Cut Tree(动态树)(LCT,Splay)
为了优化体验(其实是强迫症),蒟蒻把总结拆成了两篇,方便不同学习阶段的Dalao们切换. LCT总结--应用篇戳这里 概念.性质简述 首先介绍一下链剖分的概念(感谢laofu的讲课) 链剖分,是指一类 ...
- BZOJ 3282 Link Cut Tree (LCT)
题目大意:维护一个森林,支持边的断,连,修改某个点的权值,求树链所有点点权的异或和 洛谷P3690传送门 搞了一个下午终于明白了LCT的原理 #include <cstdio> #incl ...
- 模板Link Cut Tree (动态树)
题目描述 给定N个点以及每个点的权值,要你处理接下来的M个操作.操作有4种.操作从0到3编号.点从1到N编号. 0:后接两个整数(x,y),代表询问从x到y的路径上的点的权值的xor和.保证x到y是联 ...
- 洛谷.3690.[模板]Link Cut Tree(动态树)
题目链接 LCT(良心总结) #include <cstdio> #include <cctype> #include <algorithm> #define gc ...
- 【刷题】洛谷 P3690 【模板】Link Cut Tree (动态树)
题目背景 动态树 题目描述 给定n个点以及每个点的权值,要你处理接下来的m个操作.操作有4种.操作从0到3编号.点从1到n编号. 0:后接两个整数(x,y),代表询问从x到y的路径上的点的权值的xor ...
- Luogu 3690 Link Cut Tree
Luogu 3690 Link Cut Tree \(LCT\) 模板题.可以参考讲解和这份码风(个人认为)良好的代码. 注意用 \(set\) 来维护实际图中两点是否有直接连边,否则无脑 \(Lin ...
- (RE) luogu P3690 【模板】Link Cut Tree
二次联通门 : luogu P3690 [模板]Link Cut Tree 莫名RE第8个点....如果有dalao帮忙查错的话万分感激 #include <cstdio> #includ ...
- P3690 【模板】Link Cut Tree (动态树)
P3690 [模板]Link Cut Tree (动态树) 认父不认子的lct 注意:不 要 把 $fa[x]$和$nrt(x)$ 混 在 一 起 ! #include<cstdio> v ...
- LuoguP3690 【模板】Link Cut Tree (动态树) LCT模板
P3690 [模板]Link Cut Tree (动态树) 题目背景 动态树 题目描述 给定n个点以及每个点的权值,要你处理接下来的m个操作.操作有4种.操作从0到3编号.点从1到n编号. 0:后接两 ...
随机推荐
- 设置overflow:auto无效的解决办法
做项目中经常要用到滚动条,有时候给div设置overflow无效. 遇到这样的问题,只需要在 F12 Elements面板检查一下要设置overflow的元素的宽高是否大于父级元素宽高. (overf ...
- jquery实现表格复选框---多行选择问题(php变量)
1.html多选框标签行 表头的多选框,用于全选,取消全选 <th><input id='allSelected' type="checkbox">< ...
- magento 为用户注册增加一个字段
步骤 I. 加一个occupation/title字段到用户注册页,差不多在register.html的54行,在email下方加一个Occupation显示代码 代码: <li>< ...
- Android中ViewPgae中的Fragment如何确认当前页面可见的问题
由于在ViewPage中PageAdapter来管理所有的Fragment.在加载一个Fragment的时候,会自动缓存左右几个(默认是一个)页面,此时也会调用到正常的生命周期函数,onCreate, ...
- Cell的复用机制问题总结
创建方式汇总,注册和不注册Cell注册的两种方式 1.tableView registerNib:(nullable UINib *) forCellReuseIdentifier:(nonnull ...
- 【前端控件】JQuery datepicker 日期控件设置
datepicker控件可通过参数设置进行语言切换,以下可实现,系统所有日期控件默认为中文,在特定页面或者特定条件下可切换成英语!~ HTML: <!DOCTYPE html> <h ...
- 非常实用的css
.clearfix:after {content: "";display: block;visibility: hidden;height: 0;clear: both;} .cl ...
- HTML5 Canvas知识点学习笔记
版权声明:本文为博主原创文章,未经博主同意不得转载. https://blog.csdn.net/huangyibin628/article/details/30108165 canvas ① 主要作 ...
- linux每日命令(2):ps命令
ps命令真是我比较常用的命令了,只是也没咋仔细研究过,最大的用处就是写代码的时候,起了多进程,就会占用多个进程,如果程序异常了,进程确没有kill掉,那么再启动程序就会报错 正常起项目 如果进程被占用 ...
- android应用的资源
应用资源可以分为两大类: 1.无法直接访问的原生资源,保存在asset目录下. 2.可以通过R资源清单类访问的资源,保存在res目录下. 资源的类型以及存储方式: android要求在res目录下用不 ...