[模板]Link-Cut-Tree动态树
做法以后再补,先写一些注意事项。
做法以后也不补了,直接看这个吧。https://www.cnblogs.com/candy99/p/6271344.html
1.rotate其实是最容易写错的地方(对于丝毫没有掌握splay蒟蒻我来说),一定要仔细检查
2.splay之前需要先从根开始往下pushdown一遍
3.注意getRoot(findRoot)和setRoot(makeRoot)对节点位置带来的影响
4.access的结束条件是x==0!!不是fa[x]!!(这个zz才会写错吧) (没错就是我写错了还查了半天)
5.pushdown的位置、是否splay(x)所带来的玄学问题(我哪想的明白啊)
luogu3690(连边、断边、改点值、查询链上异或和)
#include<cstdio>
#include<cstring>
#include<algorithm>
#include<vector>
#include<queue>
#include<map>
#include<cmath>
#include<ctime>
#include<set>
#define pa pair<int,int>
#define lowb(x) ((x)&(-(x)))
#define REP(i,n0,n) for(i=n0;i<=n;i++)
#define PER(i,n0,n) for(i=n;i>=n0;i--)
#define MAX(a,b) ((a>b)?a:b)
#define MIN(a,b) ((a<b)?a:b)
#define CLR(a,x) memset(a,x,sizeof(a))
#define rei register int
using namespace std;
typedef long long ll;
const int maxn=; ll rd(){
ll x=;char c=getchar();int neg=;
while(c<''||c>''){if(c=='-') neg=-;c=getchar();}
while(c>=''&&c<='') x=x*+c-'',c=getchar();
return x*neg;
} int N,M;
int ch[maxn][],v[maxn],xs[maxn],fa[maxn];
bool rev[maxn]; inline void pushrev(int x){swap(ch[x][],ch[x][]);rev[x]^=;}
inline void update(int x){xs[x]=xs[ch[x][]]^xs[ch[x][]]^v[x];}
inline void pushdown(int x){
if(!rev[x]) return;
if(ch[x][]) pushrev(ch[x][]);
if(ch[x][]) pushrev(ch[x][]);
rev[x]=;
}
inline bool isRoot(int x){return ch[fa[x]][]!=x&&ch[fa[x]][]!=x;}
inline bool isRson(int x){return x==ch[fa[x]][];}
inline void rotate(int x){
int f=fa[x],ff=fa[f];bool b=isRson(x);
if(ch[x][b^]) fa[ch[x][b^]]=f;ch[f][b]=ch[x][b^];
if(!isRoot(f)) ch[ff][isRson(f)]=x;fa[x]=ff;
fa[f]=x;ch[x][b^]=f;update(f);update(x);
}
void pushall(int x){
if(!isRoot(x)) pushall(fa[x]);
pushdown(x);
}
inline void splay(int x){
pushall(x);
while(!isRoot(x)&&!isRoot(fa[x])){
if(isRson(x)==isRson(fa[x])) rotate(fa[x]);rotate(x);
}if(!isRoot(x)) rotate(x);
}
inline void access(int x){
for(int lst=;x;lst=x,x=fa[x]){
splay(x);ch[x][]=lst;update(x);
}
}
inline int getRoot(int x){
access(x);splay(x);
while(ch[x][]){pushdown(x);x=ch[x][];}return x;
}
inline void setRoot(int x){
access(x);splay(x);pushrev(x);
}
inline void link(int x,int y){
setRoot(x);
if(getRoot(y)!=x) fa[x]=y;
}
inline void cut(int x,int y){
setRoot(x);
if(getRoot(y)!=x||fa[x]!=y||ch[x][]) return;
ch[y][]=fa[x]=;update(y);
}
inline void change(int x,int k){
splay(x);v[x]=k;update(x);
}
inline int query(int x,int y){
setRoot(x);access(y);splay(y);
return xs[y];
} int main(){
//freopen("testdata.in","r",stdin);
rei i,j,k;
N=rd(),M=rd();//printf("%d %d\n",N,M);
for(i=;i<=N;i++) v[i]=xs[i]=rd();
while(M--){
int a=rd(),x=rd(),y=rd();
if(a==) printf("%d\n",query(x,y));
else if(a==) link(x,y);
else if(a==) cut(x,y);
else if(a==) change(x,y);
}
return ;
}
luogu3690
luogu3203 弹飞绵羊(连边、断边、查询链长)
#include<cstdio>
#include<cstring>
#include<algorithm>
#include<vector>
#include<queue>
#include<map>
#include<cmath>
#include<ctime>
#include<set>
#define pa pair<int,int>
#define lowb(x) ((x)&(-(x)))
#define REP(i,n0,n) for(i=n0;i<=n;i++)
#define PER(i,n0,n) for(i=n;i>=n0;i--)
#define MAX(a,b) ((a>b)?a:b)
#define MIN(a,b) ((a<b)?a:b)
#define CLR(a,x) memset(a,x,sizeof(a))
#define rei register int
#define lt ch[x][0]
#define rt ch[x][1]
using namespace std;
const int maxn=;
typedef long long ll; ll rd(){
ll x=;char c=getchar();int neg=;
while(c<''||c>''){if(c=='-') neg=-;c=getchar();}
while(c>=''&&c<='') x=x*+c-'',c=getchar();
return x*neg;
} int N,M;
int fa[maxn],ch[maxn][],siz[maxn],to[maxn];
bool rev[maxn]; inline void update(int x){siz[x]=(lt?siz[lt]:)+(rt?siz[rt]:)+;}
inline void pushrev(int x){
rev[x]^=;swap(lt,rt);
}
inline void pushdown(int x){
if(!rev[x]) return;
if(lt) pushrev(lt);
if(rt) pushrev(rt);
rev[x]=;
}
inline bool isRoot(int x){return ch[fa[x]][]!=x&&ch[fa[x]][]!=x;}
inline bool isRson(int x){return x==ch[fa[x]][];}
inline void rotate(int x){
int f=fa[x],ff=fa[f];bool b=isRson(x);
if(!isRoot(f)) ch[ff][isRson(f)]=x;fa[x]=ff;
if(ch[x][b^]) fa[ch[x][b^]]=f;ch[f][b]=ch[x][b^];
ch[x][b^]=f;fa[f]=x;update(f);update(x);
}
inline void pushdall(int x){
if(!isRoot(x)) pushdall(fa[x]);pushdown(x);
}
inline void splay(int x){
pushdall(x);
while(!isRoot(x)&&!isRoot(fa[x])){
if(isRson(x)==isRson(fa[x])) rotate(fa[x]);
else rotate(x);rotate(x);
}if(!isRoot(x)) rotate(x);
}
inline void access(int x){
for(int y=;x;y=x,x=fa[x]){
splay(x);rt=y;update(x);
}
}
inline void setRoot(int x){
access(x);splay(x);
pushrev(x);
}
inline int getRoot(int x){
access(x);splay(x);
while(lt){
pushdown(x);x=lt;
}return x;
}
inline void link(int x,int y){//x->y
setRoot(x);
access(y);splay(y);fa[x]=y;
}
inline void cut(int x,int y){
setRoot(x);access(y);splay(y);
ch[y][]=fa[x]=;update(y);
}
inline int query(int x,int y){
setRoot(x);
access(y);splay(y);
//printf("%d %d\n",ch[y][0],ch[y][1]);
return siz[y];
}
inline void change(int x,int k){
if(x+k>N&&x+to[x]>N) return;
if(to[x]) cut(x,MIN(x+to[x],N+));
link(x,MIN(x+k,N+));
to[x]=k;
} int main(){
//freopen("3203.in","r",stdin);
rei i,j,k;N=rd();
REP(i,,N) change(i,rd()),siz[i]=;siz[N+]=;
M=rd();REP(i,,M){
j=rd(),k=rd()+;
if(j==) printf("%d\n",query(N+,k)-);
else change(k,rd());
}
return ;
}
luogu3203
[模板]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 ...
- LuoguP3690 【模板】Link Cut Tree (动态树) LCT模板
P3690 [模板]Link Cut Tree (动态树) 题目背景 动态树 题目描述 给定n个点以及每个点的权值,要你处理接下来的m个操作.操作有4种.操作从0到3编号.点从1到n编号. 0:后接两 ...
随机推荐
- Linux Shell完成Qt程序的自动部署
#!/bin/sh #取当前脚本的绝对路径 srcDir=$(cd ")";pwd) #设置库所在路径 libDir=${srcDir}"/J1900RunLib/*&q ...
- LVM : 简介
在对磁盘分区的大小进行规划时,往往不能确定这个分区要使用的空间的大小.而使用 fdisk.gdisk 等工具对磁盘分区后,每个分区的大小就固定了.如果分区设置的过大,就白白浪费了磁盘空间:如果分区设置 ...
- SpringMvc执行过程
--Test过程: 1. 先执行各种 Filter 2. HttpServlet.service(ServletRequest req, ServletResponse res) 3. HttpSer ...
- 更换Ubuntu源为国内源的操作记录
我们都知道,Ubuntu的官方源对于国内用户来说是比较慢的,可以将它的源换成国内的源(比如阿里源),这样用起来就很快了.下面记录下更换操作: 首先了解下/etc/apt/sources.list文件 ...
- Redis主从复制原理总结
和Mysql主从复制的原因一样,Redis虽然读取写入的速度都特别快,但是也会产生读压力特别大的情况.为了分担读压力,Redis支持主从复制,Redis的主从结构可以采用一主多从或者级联结构,Redi ...
- C_数据结构_递归实现求阶乘
# include <stdio.h> int main(void) { int val; printf("请输入一个数字:"); printf("val = ...
- Python-dict-12
字典 Why:咱们目前已经学习到的容器型数据类型只有list,那么list够用?他有什么缺点呢? 1. 列表可以存储大量的数据类型,但是如果数据量大的话,他的查询速度比较慢. 2. 列表只能按照顺序存 ...
- Week 3 结对编程
Group: 杜正远 潘礼鹏 结对编程: 优点: 集体荣誉感.你们已经是一个集体了,一定得为对方着想负责. 1.看对方的代码,彼此会互相学习到一些奇妙的方法. 2.结对编程能把两个事情分开,降低复杂度 ...
- Unigine mesh顶点坐标转换精度问题
本问题虽然与Unigine引擎相关,但对其他精度问题也有参考价值. 问题: 将精细模型顶点从自身参考系的相对坐标(类似4378.95020,4561.00000,31.3887463) 转到椭球面世界 ...
- <构建之法>8,9,10章的读后感
第八章 这一章主要讲的是需求分析,主要介绍在客户需求五花八门的情况下,软件团队如何才能准确而全面地找到这些需求. 第九章 问题:我们现在怎样培养才能成为一名合格的PM呢? 第十章 问题:如果典型用户吴 ...