[Data]Link cut tree
Link Cut Tree
其实本人觉得LCT对于已经学过树剖与Splay的大佬是很容易理解接受的;
LCT是有树链与Splay结合而成的动态树;什么是动态树呢,就是维护森林的联通性的总称;
先介绍一些概念:
1.prefered child:最后被它的点在x的儿子p节点的子树中,那么p为x的偏爱子节点(相当于树剖中的重儿子)
2.prefered edge:父节点与它的偏爱子节点的边(相当于树剖中的重边)
3.prefered path:由偏爱边连接而成的路径为偏爱路径(相当于树剖中的重链)
我们学LCT时可以发现,每个点只在一条prefered path上,那么这样的话所有的prefered path就可以表示整棵树了,我们可以在每条prefered path 上建一棵splay,关键字为深度
也就是在每棵Splay中,左节点的深度都比当前节点小,右节点的深度都比当前节点深度大;这样,每棵spaly我们把它称作Auxiliary tree(辅助树),每棵辅助树的根节点的父亲
保存与上一棵辅助树的哪个点相连;整棵Splay在原树上相当于一条链(中序遍历);
原树中的深度是递增的,辅助树中的左右子树是以深度为权值的!
易混点:
原树的根节点!=辅助树中的根节点
原树的左右儿子不等于辅助树的左右儿子
现在来说下一些基本操作:
1.access(x) 访问x节点:切断x与其原先Prefered child 的联系,由于prefered path与prefered child的定义,我们访问一个节点,那么这个点到根节点的所有边都是prefered edge;由于每个点只能有一个prefered child;所以我们需把节点与它原来的prefered child断开,连接这条新的prefered path;先把x splay到根节点,然后更新它的右子节点,直到x的fa 为空;
2.make root(x) access(x)后,splay到根,然后由于权值是深度,所以为了维护左子树权值小于右子树性质,我们还需区间翻转一下;
3.link(x,y) 连边,只需makeroot(x),然后把x的父亲指向y即可;
4.cut(x,y) 删边,先makeroot(x),然后access(y),此时x与y已在同一棵splay中,然后再splay(y),那么x就在y的左儿子中;
最后放下代码:(luogu 3690)
1 #include<cstdio> 2 #include<cmath> 3 #include<algorithm> 4 #define maxn 300233 5 using namespace std; 6 int stack[maxn]; 7 struct hh{ 8 int c[2],fa,val,sum; 9 bool rev; 10 }tree[maxn]; 11 int read(){ 12 int s=0; 13 char c=getchar(); 14 while(c<48||c>57) c=getchar(); 15 while(c>=48&&c<=57){ 16 s=s*10+c-48;c=getchar();} 17 return s; 18 } 19 20 inline void update(int x){ 21 tree[x].sum=tree[tree[x].c[0]].sum^tree[x].val 22 ^tree[tree[x].c[1]].sum; 23 } 24 inline void pushdown(int x){ 25 if(!tree[x].rev) return; 26 int l=tree[x].c[0],r=tree[x].c[1]; 27 if(l) tree[l].rev^=1; 28 if(r) tree[r].rev^=1; 29 swap(tree[x].c[0],tree[x].c[1]); 30 tree[x].rev^=1; 31 } 32 bool isroot(int x){ 33 return tree[tree[x].fa].c[0]!=x&&tree[tree[x].fa].c[1]!=x; 34 } 35 bool get(int x) { 36 return x==tree[tree[x].fa].c[1];} 37 void rotate(int x){ 38 int f=tree[x].fa,ff=tree[tree[x].fa].fa,opt=get(x); 39 tree[f].c[opt]=tree[x].c[opt^1]; 40 tree[tree[x].c[opt^1]].fa=f; 41 if(!isroot(f)) tree[ff].c[get(f)]=x; 42 tree[x].fa=ff;tree[f].fa=x; 43 tree[x].c[opt^1]=f; 44 update(f);update(x); 45 } 46 void splay(int x){ 47 //pushdown(x); 48 int top=0,tmp=x;stack[++top]=x; 49 while(!isroot(tmp))stack[++top]=tree[tmp].fa,tmp=tree[tmp].fa; 50 while(top)pushdown(stack[top]),top--; 51 while(!isroot(x)){ 52 // if(!isroot(tree[x].fa)) rotate(get(tree[x].fa)==get(x)?tree[x].fa:x); 53 // x=tree[x].fa; 54 rotate(x); 55 } 56 } 57 void access(int x){ 58 int son=0; 59 while(x){ 60 splay(x);tree[x].c[1]=son; 61 update(x);son=x;x=tree[x].fa; 62 } 63 } 64 void makeroot(int x){ 65 access(x);splay(x);tree[x].rev^=1; 66 } 67 void link(int x,int y){ 68 makeroot(x);tree[x].fa=y; 69 splay(x); 70 } 71 void cut(int x,int y){ 72 makeroot(x);access(y); 73 splay(y);tree[y].c[0]=tree[x].fa=0; 74 } 75 int query(int x,int y){ 76 makeroot(x);access(y);splay(y); 77 return tree[y].sum; 78 } 79 int getfa(int x){ 80 access(x);splay(x); 81 while(tree[x].c[0]){ 82 pushdown(x);x=tree[x].c[0]; 83 splay(x); 84 } 85 return x; 86 } 87 void change(int x,int y){ 88 makeroot(x); 89 tree[x].val=y; 90 update(x); 91 } 92 int main(){ 93 int n,m,i,x,y,opt; 94 n=read();m=read(); 95 for(i=1;i<=n;i++){ 96 tree[i].val=read(); 97 tree[i].sum=tree[i].val; 98 } 99 while(m--){ 100 opt=read();x=read();y=read(); 101 if(opt==0) printf("%d\n",query(x,y)); 102 else if(opt==1) {if(getfa(x)!=getfa(y))link(x,y);} 103 else if(opt==2) {if(getfa(x)==getfa(y)) cut(x,y);} 104 else change(x,y);} 105 }
View Code
转载于:https://www.cnblogs.com/Fish-/p/8167122.html
[Data]Link cut tree相关推荐
- 15行代码AC——Link/Cut Tree CodeForces - 614A(爆long long处理+快速幂讲解)
励志用少的代码做高效表达 Problem describe Programmer Rostislav got seriously interested in the Link/Cut Tree dat ...
- Link Cut Tree详解
Link Cut Tree ==Warning:千万不要跳读== 参考博客:https://www.cnblogs.com/flashhu/p/8324551.html 什么是动态树? 动态树问题, ...
- 模板:Link Cut Tree(LCT)
文章目录 前言 解析 原理 rotate(x) splay(x) access(x) findroot(x) makeroot(x) split(x,y) link(x,y) cut(x,y) pus ...
- Link Cut Tree 学习笔记
Link Cut Tree 学习笔记 说在前边 最近补 CF 碰见一道 LCT ,就打算学习一下这个东西...顺便复习一下 splay. 具体算法及实现 参考了FlashHu, Candy? P369 ...
- Link/Cut Tree学习笔记
最近正是实验课的高峰期,我数了一下,除了毛概没有实验课,其他的课都有实验课...不过好在这些实验都不是很难.我尽力挤出时间用来刷题. 简介 Link/Cut Tree和树链剖分很相似,二者处理的问题也 ...
- link cut tree 入门
鉴于最近写bzoj还有51nod都出现写不动的现象,决定学习一波厉害的算法/数据结构. link cut tree:研究popoqqq那个神ppt. bzoj1036:维护access操作就可以了. ...
- 洛谷 - P3690 【模板】Link Cut Tree (动态树)(LCT模板)
题目链接:点击查看 题目大意:给出 n 个带权节点,需要执行 m 次操作,每次操作分为四种类型: 0 x y 代表询问从 x 到 y 的路径上的点的权值的 xor 和.保证 x 到 y 是联通的. 1 ...
- luogu P3690 【模板】Link Cut Tree (动态树)
嘟嘟嘟 LCT竟然看了整整一天,但好歹是看懂了. 教程这里不写,强烈推荐 闪狐大佬的博客 . 但是还是有几句想说的. 1.尽管LCT和splay很像,但是有一些细节还是不一样的.首先是rotate,我 ...
- Link Cut Tree学习笔记
捋一下思路 模板题:https://www.luogu.org/problemnew/show/P3690 推荐LCT的教程,个人认为很详细,本文做了部分引用:https://www.luogu.or ...
- P3690-[模板]Link Cut Tree(动态树)【Splay】
正题 题目链接:https://www.luogu.org/problem/P3690 题目大意 nnn个点mmm个操作,要求支持 询问路径异或和 连接一条边(若x,yx,yx,y没联通) 删除一条边 ...
最新文章
- 数学表达式解析器简介
- python爬虫用urllib还是reques,python爬虫中urllib.request和requests有什么区别?
- 浏览器插件 火狐插件
- 操作系统中避免死锁的银行家算法【表面C++实际C语言】一学就废的菜鸡代码
- sql server 游标的使用方法
- 新一代企业操作系统:专属钉钉解决方案全新上线
- C++ const对象
- 一起来学SpringBoot | 第四篇:整合Thymeleaf模板
- 轻量级HTTP服务器Nginx(Nginx性能优化技巧)
- mysql中更新的命令是_MySQL 语言中,更新表数据的命令是( )。_学小易找答案
- 代码块(block)之函数体(二)
- MySQL 到底能不能放到 Docker 里跑? 1
- 2021-2025年中国IT业的利好机遇
- ecmobile php开发文档,ecmobile PHP接口说明文档之购物车(cart/create|list|detele|update)
- mysql每五分钟取一次数据_mysql – 给定时间内每5分钟的平均数据
- 2021-12-12
- 26个颠覆世界的 3D 打印产品,未来将会创造另一个新的世界
- 携手共进 智享未来丨美格智能2023年代理商合作伙伴大会成功举办
- Ollydbg使用技巧
- android webrtc教程,WebRTC 入门教程(一)| 搭建WebRTC信令服务器
热门文章
- gtx1050ti最稳定的驱动_最便宜图灵吃鸡卡 华硕GTX 1650评测
- javascript基础之拖拽(1)(详细篇)--dataTransfer对象
- linux ubuntu/centos相关收藏
- 洛谷P3233 [HNOI2014]世界树
- href 和 src 区别
- VM虚拟机,Linux系统安装tools过程遇到 what is the location of the “ifconfig” program
- 做一个消息自动回复,但是回复内容可以在网页上面输入,用input接收,错了,别人有新增选项,本身就是在页面进行新增,页面维护...
- 那些盒模型在IE6中的BUG们,工程狮的你可曾遇到过?
- (转)MapReduce二次排序
- 微软高性能网络编程示例程序