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 ...
随机推荐
- A4纸网页打印 html网页页面的宽度设置成多少
A4纸竖向打印,html网页页面的宽度设置成多少?这个问题是我们大家所疑惑的,于是网上搜集整理下,希望可以帮助你们 最近开发项目时遇到了网页打印的问题,这是问题之二,打印宽度设置 在公制长度单位与屏幕 ...
- [spring]xml配置文件---节点解释
转载:https://blog.csdn.net/u012099568/article/details/51423837
- svn diff color
大致有两种方式: 1,在bashrc中添加如下脚本 svndiff() { svn diff "${@}" | colordiff } 2,修改svn的配置文件 $ vim ~/. ...
- C++双向循环链表实现
双向循环链表C++实现 1.单链表: 结构图: 2.双向链表: 3.双向循环链表: 对于本程序中,则是给定一个_head 头结点,而不是指针,因为这样更加方便避免一些空判断问题 /* 版权信息:狼 ...
- jsp获取绝对路径
在JavaWeb开发中,常使用绝对路径的方式引入javaScript和CSS文件,这样可以避免因为目录变动导致引入文件找不到的情况,常用的做法是: 一.使用${pageContext.request. ...
- msys git 安装配置、git命令行使用
安装 .安装msys git客户端程序 .打开git bash,命令ssh-keygen –C “admin@test.cn “ –t rsa .复制C:\Users\felix\.ssh\id_rs ...
- IOS-简单动画
iOS那些简单的动画(不定期更新) 字数669 阅读1118 评论16 喜欢59 关于 Core Animation Core Animation是一组非常强大的动画处理API,使用它能做出很多优雅的 ...
- 009-对象—— 构造方法__construct析构方法__destruct使用方法 PHP重写与重载
<?php /**构造方法__construct析构方法__destruct使用方法 PHP重写与重载 */ //构造方法:当实例化对象时,自动运行的方法 /*class channel{ fu ...
- c# 三种取整方法 向上取整 向下取整 四舍五入
Math.Round:四舍六入五取整 Math.Ceiling:向上取整,只要有小数都加1 Math.Floor:向下取整,总是舍去小数
- 【WPF】影城POS的前世今生
前言 POS从16年底开始设计到现在都过去快两年了,这里我做一个简单的回顾. 技术选型 NativeUI:性能最高,开发难度最大,代表产品QQ和微信,没有基因没有技术栈. Electron+H5:不支 ...