UPD:更新了写法。

【模板】Link Cut Tree

给定n个点以及每个点的权值,要你处理接下来的m个操作。操作有4种。操作从0到3编号。点从1到n编号。

  1. 后接两个整数(x,y),代表询问从x到y的路径上的点的权值的xor和。保证x到y是联通的。

  2. 后接两个整数(x,y),代表连接x到y,若x到y已经联通则无需连接。

  3. 后接两个整数(x,y),代表删除边(x,y),不保证边(x,y)存在。

  4. 后接两个整数(x,y),代表将点x上的权值变成y。

数据范围: \(1 \leq N, M \leq 3 \cdot {10}^5\)

http://www.cnblogs.com/flashhu/p/8324551.html

https://www.cnblogs.com/candy99/p/6271344.html

时间复杂度\(O(n+m \log n)\)

CO int N=100000+10;
int fa[N],ch[N][2],rev[N];
int val[N],sum[N]; #define lc ch[x][0]
#define rc ch[x][1]
IN bool nroot(int x){
return x==ch[fa[x]][0] or x==ch[fa[x]][1];
}
IN void push_up(int x){
sum[x]=sum[lc]^val[x]^sum[rc];
}
IN void push_down(int x){
if(rev[x]){
swap(lc,rc);
rev[lc]^=1,rev[rc]^=1;
rev[x]=0;
}
}
IN void rotate(int x){
int y=fa[x],z=fa[y],l=x==ch[y][1],r=l^1;
if(nroot(y)) ch[z][y==ch[z][1]]=x;fa[x]=z;
ch[y][l]=ch[x][r],fa[ch[x][r]]=y;
ch[x][r]=y,fa[y]=x;
push_up(y);
}
void splay(int x){
vector<int> stk(1,x);
for(int i=x;nroot(i);) stk.push_back(i=fa[i]);
for(;stk.size();stk.pop_back()) push_down(stk.back());
for(;nroot(x);rotate(x)){
int y=fa[x],z=fa[y];
if(nroot(y)) rotate((x==ch[y][1])!=(y==ch[z][1])?x:y);
}
push_up(x);
}
void access(int x){
for(int y=0;x;y=x,x=fa[x])
splay(x),rc=y,push_up(x);
}
void make_root(int x){
access(x),splay(x),rev[x]^=1;
}
int find_root(int x){
access(x),splay(x);
while(lc) x=lc;
splay(x);
return x;
}
#undef lc
#undef rc int main(){
int n=read<int>(),m=read<int>();
for(int i=1;i<=n;++i) read(val[i]);
while(m--)switch(read<int>()){
case 0:{
int x=read<int>(),y=read<int>();
make_root(x),access(y),splay(y);
printf("%d\n",sum[y]);
break;
}
case 1:{
int x=read<int>(),y=read<int>();
make_root(x);
if(find_root(y)!=x) fa[x]=y;
break;
}
case 2:{
int x=read<int>(),y=read<int>();
make_root(x);
if(find_root(y)==x and fa[y]==x and !ch[y][0]){
fa[y]=ch[x][1]=0;
push_up(x);
}
break;
}
default:{
int x=read<int>();
splay(x),read(val[x]),push_up(x);
break;
}
}
return 0;
}

洞穴勘测

辉辉热衷于洞穴勘测。某天,他按照地图来到了一片被标记为JSZX的洞穴群地区。经过初步勘测,辉辉发现这片区域由n个洞穴(分别编号为1到n)以及若干通道组成,并且每条通道连接了恰好两个洞穴。假如两个洞穴可以通过一条或者多条通道按一定顺序连接起来,那么这两个洞穴就是连通的,按顺序连接在一起的这些通道则被称之为这两个洞穴之间的一条路径。洞穴都十分坚固无法破坏,然而通道不太稳定,时常因为外界影响而发生改变,比如,根据有关仪器的监测结果,123号洞穴和127号洞穴之间有时会出现一条通道,有时这条通道又会因为某种稀奇古怪的原因被毁。

辉辉有一台监测仪器可以实时将通道的每一次改变状况在辉辉手边的终端机上显示:

  • 如果监测到洞穴u和洞穴v之间出现了一条通道,终端机上会显示一条指令 Connect u v

  • 如果监测到洞穴u和洞穴v之间的通道被毁,终端机上会显示一条指令 Destroy u v

经过长期的艰苦卓绝的手工推算,辉辉发现一个奇怪的现象:无论通道怎么改变,任意时刻任意两个洞穴之间至多只有一条路径。因而,辉辉坚信这是由于某种本质规律的支配导致的。因而,辉辉更加夜以继日地坚守在终端机之前,试图通过通道的改变情况来研究这条本质规律。然而,终于有一天,辉辉在堆积成山的演算纸中崩溃了……他把终端机往地面一砸(终端机也足够坚固无法破坏),转而求助于你,说道:“你老兄把这程序写写吧”。

辉辉希望能随时通过终端机发出指令 Query u v,向监测仪询问此时洞穴u和洞穴v是否连通。现在你要为他编写程序回答每一次询问。已知在第一条指令显示之前,JSZX洞穴群中没有任何通道存在。

100%的数据满足n≤10000, m≤200000

保证所有Destroy指令将摧毁的是一条存在的通道

LCT模板题,总结了一下我所见过的最简洁的写法。时间复杂度\(O(m \log n)\)

co int N=1e4+1;
namespace T{
int fa[N],ch[N][2],st[N],rev[N];
#define lc ch[x][0]
#define rc ch[x][1]
bool nroot(int x){return ch[fa[x]][0]==x||ch[fa[x]][1]==x;}
void pushdown(int x){
if(rev[x]){
std::swap(lc,rc);
rev[lc]^=1,rev[rc]^=1;
rev[x]=0;
}
}
void rotate(int x){
int y=fa[x],z=fa[y],l=x==ch[y][1],r=l^1;
if(nroot(y)) ch[z][y==ch[z][1]]=x;fa[x]=z;
ch[y][l]=ch[x][r],fa[ch[x][r]]=y;
ch[x][r]=y,fa[y]=x;
}
void splay(int x){
int y=x,z=0;
st[++z]=y;
while(nroot(y)) st[++z]=y=fa[y];
while(z) pushdown(st[z--]);
for(;nroot(x);rotate(x)){
y=fa[x],z=fa[y];
if(nroot(y)) rotate(y==ch[z][1]^x==ch[y][1]?x:y);
}
}
void access(int x){
for(int y=0;x;x=fa[y=x])
splay(x),rc=y;
}
void makeroot(int x){
access(x),splay(x),rev[x]^=1;
}
int findroot(int x){
access(x),splay(x);
while(lc) x=lc;
return x;
}
void link(int x,int y){
makeroot(x),fa[x]=y;
}
void cut(int x,int y){
makeroot(x),access(y),splay(y),ch[y][0]=fa[x]=0;
}
}
int main(){
int n=read<int>(),m=read<int>();
char opt[10];
int x,y;
while(m--){
scanf("%s",opt);
read(x),read(y);
if(opt[0]=='C') T::link(x,y);
else if(opt[0]=='D') T::cut(x,y);
else puts(T::findroot(x)==T::findroot(y)?"Yes":"No");
}
return 0;
}

LG3690 【模板】Link Cut Tree (动态树)的更多相关文章

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

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

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

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

  3. Link Cut Tree 动态树 小结

    动态树有些类似 树链剖分+并查集 的思想,是用splay维护的 lct的根是动态的,"轻重链"也是动态的,所以并没有真正的轻重链 动态树的操作核心是把你要把 修改/询问/... 等 ...

  4. LCT(link cut tree) 动态树

    模板参考:https://blog.csdn.net/saramanda/article/details/55253627 综合各位大大博客后整理的模板: #include<iostream&g ...

  5. 洛谷P3690 Link Cut Tree (动态树)

    干脆整个LCT模板吧. 缺个链上修改和子树操作,链上修改的话join(u,v)然后把v splay到树根再打个标记就好. 至于子树操作...以后有空的话再学(咕咕咕警告) #include<bi ...

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

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

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

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

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

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

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

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

随机推荐

  1. Shell 命令挂后台执行

    使用nohup命令,结合& #!/bin/bash #挂后台执行文件 kimbo_test.sh nohup >& & 说明:0 是标准输入(STDIN),1 是标准输出 ...

  2. OpenGL全景视频

    全景视频其实在实现上和一般的视频播放基本差不多,解码可以用ffmpeg,只是对解码后的图片在绘制的时候要绘制在一个球上(我这里是球,好像有说有的格式要绘制在四面体上的,美做深入研究),而不是画在一个表 ...

  3. css3 transform matrix矩阵的使用

      Transform 执行顺序问题 — 后写先执行 matrix(a,b,c,d,e,f) 矩阵函数 •通过矩阵实现缩放 x轴缩放 a=x*a    c=x*c     e=x*e; y轴缩放 b= ...

  4. laravel中的validator()类验证的使用

  5. 转载:【Oracle 集群】RAC知识图文详细教程(二)--Oracle 集群概念及原理

    文章导航 集群概念介绍(一) ORACLE集群概念和原理(二) RAC 工作原理和相关组件(三) 缓存融合技术(四) RAC 特殊问题和实战经验(五) ORACLE 11 G版本2 RAC在LINUX ...

  6. bzoj3402

    题解: spfa最短路 然后枚举判断奇数 代码: #include<bits/stdc++.h> using namespace std; ; ]; void jb(int x,int y ...

  7. js中Function的apply方法与call方法理解

    最近在使用jQuery的$.each方法时很,突然想到$.each($('div'),function(index,entity){});中的这个index和entity是哪冒出来的,而且可有可无的, ...

  8. 《Effective C++》第4章 设计与声明(1)-读书笔记

    章节回顾: <Effective C++>第1章 让自己习惯C++-读书笔记 <Effective C++>第2章 构造/析构/赋值运算(1)-读书笔记 <Effecti ...

  9. node 垃圾回收

    一些思考 回收 nodejs垃圾回收 跟浏览器js不同,  以下代码会找出内存泄露 var theThing = null var replaceThing = function () { var o ...

  10. Unity3D查找丢失材质和脚本工具

    笔者介绍:姜雪伟,IT公司技术合伙人,IT高级讲师,CSDN社区专家,特邀编辑,畅销书作者,已出版书籍:<手把手教你架构3D游戏引擎>电子工业出版社和<Unity3D实战核心技术详解 ...