LG3690 【模板】Link Cut Tree (动态树)
UPD:更新了写法。
【模板】Link Cut Tree
给定n个点以及每个点的权值,要你处理接下来的m个操作。操作有4种。操作从0到3编号。点从1到n编号。
后接两个整数(x,y),代表询问从x到y的路径上的点的权值的xor和。保证x到y是联通的。
后接两个整数(x,y),代表连接x到y,若x到y已经联通则无需连接。
后接两个整数(x,y),代表删除边(x,y),不保证边(x,y)存在。
后接两个整数(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 (动态树)的更多相关文章
- LCT总结——概念篇+洛谷P3690[模板]Link Cut Tree(动态树)(LCT,Splay)
为了优化体验(其实是强迫症),蒟蒻把总结拆成了两篇,方便不同学习阶段的Dalao们切换. LCT总结--应用篇戳这里 概念.性质简述 首先介绍一下链剖分的概念(感谢laofu的讲课) 链剖分,是指一类 ...
- 洛谷.3690.[模板]Link Cut Tree(动态树)
题目链接 LCT(良心总结) #include <cstdio> #include <cctype> #include <algorithm> #define gc ...
- Link Cut Tree 动态树 小结
动态树有些类似 树链剖分+并查集 的思想,是用splay维护的 lct的根是动态的,"轻重链"也是动态的,所以并没有真正的轻重链 动态树的操作核心是把你要把 修改/询问/... 等 ...
- LCT(link cut tree) 动态树
模板参考:https://blog.csdn.net/saramanda/article/details/55253627 综合各位大大博客后整理的模板: #include<iostream&g ...
- 洛谷P3690 Link Cut Tree (动态树)
干脆整个LCT模板吧. 缺个链上修改和子树操作,链上修改的话join(u,v)然后把v splay到树根再打个标记就好. 至于子树操作...以后有空的话再学(咕咕咕警告) #include<bi ...
- 洛谷P3690 [模板] Link Cut Tree [LCT]
题目传送门 Link Cut Tree 题目背景 动态树 题目描述 给定n个点以及每个点的权值,要你处理接下来的m个操作.操作有4种.操作从0到3编号.点从1到n编号. 0:后接两个整数(x,y),代 ...
- 模板Link Cut Tree (动态树)
题目描述 给定N个点以及每个点的权值,要你处理接下来的M个操作.操作有4种.操作从0到3编号.点从1到N编号. 0:后接两个整数(x,y),代表询问从x到y的路径上的点的权值的xor和.保证x到y是联 ...
- 【刷题】洛谷 P3690 【模板】Link Cut Tree (动态树)
题目背景 动态树 题目描述 给定n个点以及每个点的权值,要你处理接下来的m个操作.操作有4种.操作从0到3编号.点从1到n编号. 0:后接两个整数(x,y),代表询问从x到y的路径上的点的权值的xor ...
- P3690 【模板】Link Cut Tree (动态树)
P3690 [模板]Link Cut Tree (动态树) 认父不认子的lct 注意:不 要 把 $fa[x]$和$nrt(x)$ 混 在 一 起 ! #include<cstdio> v ...
随机推荐
- Android-----代码实现打开手机第三方应用APP
最近做一个项目,有一个需要启动第三方应用,和微信的地图查看差不多,需要启动高德,百度或腾讯地图来查看:特来分享,希望有所帮助. 案例效果如图: 要想启动第三方:首先要知道他的包名 一:高德 高德:co ...
- flask学习(三):flask入门(URL)
一. flask简介 flask是一款非常流行的python web框架,出生于2010年,作者是Armin Ronacher,本来这个项目只是作者在愚人节的一个玩笑,后来由于非常受欢迎,进而成为一个 ...
- 2-4-搭建DHCP服务实现动态分配IP地址-NTP网络时间同步
本节所讲内容: •DHCP服务器工作原理 •使用DHCP为局域网中的机器分配IP地址 •使用DHCP为服务器分配固定IP地址 •ntpdate加计划任务同步服务器时间 ---------------- ...
- Python不同版本切换
2016年6月8日更新: 这是我早前写的一篇小文章,其实,后来也没有采用这种方法切换.电脑上安装了多个Python 版本,保证自己经常用的版本加入环境变量外,使用非系统的版本时一般使用 IDE 编辑器 ...
- js排序算法05——快速排序
终于到了传说中的快速排序算法了,快速排序的思想和归并排序一样,都是采用分治思想,不同之处在于归并每次将数组一分为二,最后将小的数组进行比较,合并为大数组.快排是每次找一个主元,也就是基准数,按照这个基 ...
- laravel5.5中查询构造器的使用
//查询构造器新增数据: public function query1() { /* $bool=DB::table('student')->insert( ['name'=>'小李',' ...
- webapi返回不带引号的字符串,解决自动加双引号的问题
返回类型改为HttpResponseMessage类型 [Route("api/TestControllers/test")] [HttpGet] public HttpRespo ...
- mysql5.6与mysql5.5不同
1.编译阶段 要明白with与without的区别,选项值分1和0,或者对应为on或off,代表支持与不支持:with的1(on)与without的0(off)是同样的,with的0(off)与wit ...
- 【WebGL】4.光源
光的类型:所有的光都是从THREE.Light继承,分为环境光THREE.AmbientLight,点光源PointLight,聚光灯THREE.SpotLight和方向光THREE.Directio ...
- Alt+Shift+R组合键,用来在一个java文件中批量的重命名变量。
myeclipse和eclipse集成编译软件,都提供了一个快捷键用来批量重命名变量:Alt+Shift+R组合键,用来在一个java文件中批量的重命名变量.扩展知识:如果想要重命名文件名,又不想手动 ...