传送门

解题思路

  \(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)的更多相关文章

  1. 洛谷P3690 [模板] Link Cut Tree [LCT]

    题目传送门 Link Cut Tree 题目背景 动态树 题目描述 给定n个点以及每个点的权值,要你处理接下来的m个操作.操作有4种.操作从0到3编号.点从1到n编号. 0:后接两个整数(x,y),代 ...

  2. LCT总结——概念篇+洛谷P3690[模板]Link Cut Tree(动态树)(LCT,Splay)

    为了优化体验(其实是强迫症),蒟蒻把总结拆成了两篇,方便不同学习阶段的Dalao们切换. LCT总结--应用篇戳这里 概念.性质简述 首先介绍一下链剖分的概念(感谢laofu的讲课) 链剖分,是指一类 ...

  3. BZOJ 3282 Link Cut Tree (LCT)

    题目大意:维护一个森林,支持边的断,连,修改某个点的权值,求树链所有点点权的异或和 洛谷P3690传送门 搞了一个下午终于明白了LCT的原理 #include <cstdio> #incl ...

  4. 模板Link Cut Tree (动态树)

    题目描述 给定N个点以及每个点的权值,要你处理接下来的M个操作.操作有4种.操作从0到3编号.点从1到N编号. 0:后接两个整数(x,y),代表询问从x到y的路径上的点的权值的xor和.保证x到y是联 ...

  5. 洛谷.3690.[模板]Link Cut Tree(动态树)

    题目链接 LCT(良心总结) #include <cstdio> #include <cctype> #include <algorithm> #define gc ...

  6. 【刷题】洛谷 P3690 【模板】Link Cut Tree (动态树)

    题目背景 动态树 题目描述 给定n个点以及每个点的权值,要你处理接下来的m个操作.操作有4种.操作从0到3编号.点从1到n编号. 0:后接两个整数(x,y),代表询问从x到y的路径上的点的权值的xor ...

  7. Luogu 3690 Link Cut Tree

    Luogu 3690 Link Cut Tree \(LCT\) 模板题.可以参考讲解和这份码风(个人认为)良好的代码. 注意用 \(set\) 来维护实际图中两点是否有直接连边,否则无脑 \(Lin ...

  8. (RE) luogu P3690 【模板】Link Cut Tree

    二次联通门 : luogu P3690 [模板]Link Cut Tree 莫名RE第8个点....如果有dalao帮忙查错的话万分感激 #include <cstdio> #includ ...

  9. P3690 【模板】Link Cut Tree (动态树)

    P3690 [模板]Link Cut Tree (动态树) 认父不认子的lct 注意:不 要 把 $fa[x]$和$nrt(x)$ 混 在 一 起 ! #include<cstdio> v ...

  10. LuoguP3690 【模板】Link Cut Tree (动态树) LCT模板

    P3690 [模板]Link Cut Tree (动态树) 题目背景 动态树 题目描述 给定n个点以及每个点的权值,要你处理接下来的m个操作.操作有4种.操作从0到3编号.点从1到n编号. 0:后接两 ...

随机推荐

  1. vue组件实例的生命周期

    <!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8&quo ...

  2. table响应式设计

    table不可用flex布局和td宽度的自适应. table外层加div.mml-table设置overflow-x:auto可以添加横向滚动条.

  3. EXCEL设置三级下拉框

    EXCEL设置三级下拉框 1.添加下拉框数据源 公式--->指定 公式--->名称管理器 2.设置第一级下拉框的值 3.第一级下拉框选出一个值 4.设置第二级下拉框(INDIRECT($A ...

  4. Python每日一题 001

    Github地址:https://github.com/Yixiaohan/show-me-the-code Talk is Cheap, show me the code. --Linus Torv ...

  5. [bzoj2839]集合计数 题解 (组合数+容斥)

    Description 一个有N个元素的集合有2^N个不同子集(包含空集),现在要在这2^N个集合中取出若干集合(至少一个),使得 它们的交集的元素个数为K,求取法的方案数,答案模1000000007 ...

  6. 16、使用jQuery的html5player播放器,进行播放

    <!-- Website Design By: www.happyworm.com --> <title>Demo : jPlayer as a video playlist ...

  7. JAVA学习之Java程序开发初次体验

    Java环境搭建算完成了,那么接下来写个Java程序走一个 开发Java程序的简单流程 1.将Java代码编写到扩展名为.java的文件中2.通过javac命令对该Java文件进行编译(生成class ...

  8. 设计模式四人帮(GOF)是什么?

    1994年,有四位作者:Erich Gamma,Richard Helm,Ralph Johnson和John Vlissides发表了一本题为<设计模式 - 可重用的面向对象软件元素>的 ...

  9. 【转】HTML5标签使用的常见误区

    最近组内进行 HTML5标签的学习,方法呢就是大家每人挑选几个标签,自己先去学习,然后给大家作讲解.这个过程大家还是挺有收获的.但是现在HTML5还处在草案阶 段,有些新的标签元素的解释也是经常有变化 ...

  10. JQuery中内容操作函数、validation表单校验

    JQuery:内容体拼接(可以直接拼接元素节点和内容节点) JQuery实现: 方案1:A.append(B); == B.appendTo(A);A的后面拼接B 方案2: A.prepend(B); ...