LCT动态树入门
LCT,link-cut-tree,一种基于splay的高级数据结构,常用于维护动态森林问题,但ta只能维护子树信息,无法修改子树信息。
首先,如果你不会splay,来这里看看吧。
接下来步入正题。
首先阐述一下个人对LCT的理解,其实你可以把LCT理解成许多棵splay,每一个联通块是一棵大splay,每个大splay中有许多的小splay,小splay的根靠虚边连上大splay,虚边是什么?即假设你从x向y连一条虚边,便只要将x父亲设为y,不用将y的儿子设为x。
但每一棵小splay中的边都是正常的树边。那么,判断一个点是不是splay的根,就要这样
inline bool isroot(int x){return ch[fa[x]][0]!=x&&ch[fa[x]][1]!=x;}
那么,每棵小splay中的到底什么?你可以将其理解为你查询的历史路径。因为每当你要统计一条路径上的信息,就要用到access操作
inline void access(int x)
{
for(register int y=0;x;y=x,x=fa[x])
{
splay(x);ch[x][1]=y;push_up(x);
}
}
access看英文就知道,这个函数相当于打通了一条从该节点到root的通道,每次将这个点旋到当前splay的root,再将以前那一棵的root接到这一棵的右儿子上,就这样一路旋上去,最后,这个点会停在主splay的最下面。
inline void makeroot(int x)
{
access(x);splay(x);rev[x]^=1;
}
makeroot,顾名思义,把这个节点作为根,为什么要打翻转标记?因为LCT维护每个点的相对深度,当你把一个点旋到root,例如是一条链,你把点从最右边旋上来,那么本来这个点应该是最深的,现在变成最浅的了,所以打上翻转标记,使他依然是最深的。
当你要统计x到y路径上的某些信息是,只需要makeroot(x),access(y),这时,x到y中间的点就是你要的路径,再splay(y),y旋上去时push_up就会把路径上的信息统计掉,所以ans就是y点信息了。
int l[N];
inline void splay(int x)
{
l[0]=0;
int y=x;
while(1)
{
l[++l[0]]=y;
if(isroot(y))break;
y=fa[y];
}
Fordown(i,l[0],1)push_down(l[i]);
while(!isroot(x))
{
//if(!isroot(fa[x]))rotate(get(x)^get(fa[x])?x:fa[x]);
rotate(x);
}
}
这里的splay,因为有翻转操作,所以要先把路径上所有点入队,从上面开始依次下放翻转标记
inline int find(int x)
{
access(x);splay(x);
while(ch[x][0])x=ch[x][0];
return x;
}
find操作,其实就是找到左边的点,用来判断两个点在不在一个联通块中
inline void link(int x,int y)
{
if(find(x)==find(y))return;
makeroot(x);
fa[x]=y;
}
inline void cut(int x,int y)
{
makeroot(x);
access(y);splay(y);
if(ch[y][0]==x)ch[y][0]=0,fa[x]=0;
}
如果你弄清楚了前面几个操作,那么link和cut操作就很简单了
最后,在rotate的时候,如果你需要维护路径上的信息就需要push_up,但因为题目的不同而push_up的东西不一样,所以要根据题目来定,这里就拿维护路径上的^值,所以这样写
inline void push_up(int x){sum[x]=val[x]^sum[ch[x][0]]^sum[ch[x][1]];}
下面是例题
洛谷LCT模板(3690)要就维护路径^值
#include<bits/stdc++.h>
using namespace std;
typedef int sign;
typedef long long ll;
#define For(i,a,b) for(register sign i=(sign)a;i<=(sign)b;++i)
#define Fordown(i,a,b) for(register sign i=(sign)a;i>=(sign)b;--i)
const int N=3e5+5;
bool cmax(sign &a,sign b){return (a<b)?a=b,1:0;}
bool cmin(sign &a,sign b){return (a>b)?a=b,1:0;}
template<typename T>T read()
{
T ans=0,f=1;
char ch=getchar();
while(!isdigit(ch)&&ch!='-')ch=getchar();
if(ch=='-')f=-1,ch=getchar();
while(isdigit(ch))ans=(ans<<3)+(ans<<1)+(ch-'0'),ch=getchar();
return ans*f;
}
void file()
{
#ifndef ONLINE_JUDGE
freopen("LCT.in","r",stdin);
freopen("LCT.out","w",stdout);
#endif
}
int n,m,val[N],sum[N];
int ch[N][2],fa[N],rev[N];
inline void push_up(int x){sum[x]=val[x]^sum[ch[x][0]]^sum[ch[x][1]];}
inline void push_down(int x)
{
if(rev[x])
{
rev[ch[x][0]]^=1;
rev[ch[x][1]]^=1;
swap(ch[x][0],ch[x][1]);
rev[x]=0;
}
}
inline bool isroot(int x){return ch[fa[x]][0]!=x&&ch[fa[x]][1]!=x;}
inline bool get(int x){return x==ch[fa[x]][1];}
inline void rotate(int x)
{
int old=fa[x],oldfa=fa[old],o=get(x);
if(!isroot(old))ch[oldfa][get(old)]=x;
fa[x]=oldfa;fa[ch[x][o^1]]=old;fa[old]=x;
ch[old][o]=ch[x][o^1];ch[x][o^1]=old;
push_up(old);push_up(x);
}
int l[N];
inline void splay(int x)
{
l[0]=0;
int y=x;
while(1)
{
l[++l[0]]=y;
if(isroot(y))break;
y=fa[y];
}
Fordown(i,l[0],1)push_down(l[i]);
while(!isroot(x))
{
if(!isroot(fa[x]))rotate(get(x)^get(fa[x])?x:fa[x]);
rotate(x);
}
}
inline void access(int x)
{
for(register int y=0;x;y=x,x=fa[x])
{
splay(x);ch[x][1]=y;push_up(x);
}
}
inline void makeroot(int x)
{
access(x);splay(x);rev[x]^=1;
}
inline int find(int x)
{
access(x);splay(x);
while(ch[x][0])x=ch[x][0];
return x;
}
inline void link(int x,int y)
{
if(find(x)==find(y))return;
makeroot(x);
fa[x]=y;
}
inline void cut(int x,int y)
{
makeroot(x);
access(y);splay(y);
if(ch[y][0]==x)ch[y][0]=0,fa[x]=0;
}
void work()
{
while(m--)
{
static int opt,x,y;
opt=read<int>();x=read<int>();y=read<int>();
if(opt==0)
{
makeroot(x);
access(y);splay(y);
printf("%d\n",sum[y]);
}
else if(opt==1)link(x,y);
else if(opt==2)cut(x,y);
else if(opt==3)
{
access(x);splay(x);
val[x]=y;push_up(x);
}
}
}
inline void input()
{
n=read<int>();m=read<int>();
For(i,1,n)sum[i]=val[i]=read<int>();
}
int main()
{
file();
input();
work();
return 0;
}
LCT动态树入门的更多相关文章
- BZOJ 2049: [Sdoi2008]Cave 洞穴勘测 (动态树入门)
2049: [Sdoi2008]Cave 洞穴勘测 Time Limit: 10 Sec Memory Limit: 259 MBSubmit: 1528 Solved: 644[Submit][ ...
- LCT 动态树 模板
洛谷:P3690 [模板]Link Cut Tree (动态树) /*诸多细节,不注意就会调死去! 见注释.*/ #include<cstdio> #include<iostream ...
- [HNOI2010]弹飞绵羊 (平衡树,LCT动态树)
题面 题解 因为每个点都只能向后跳到一个唯一的点,但可能不止一个点能跳到后面的某个相同的点, 所以我们把它抽象成一个森林.(思考:为什么是森林而不是树?) 子节点可以跳到父节点,根节点再跳就跳飞了. ...
- Fzu Problem 2082 过路费 LCT,动态树
题目:http://acm.fzu.edu.cn/problem.php?pid=2082 Problem 2082 过路费 Accept: 528 Submit: 1654Time Limit ...
- Bzoj 2243: [SDOI2011]染色 树链剖分,LCT,动态树
2243: [SDOI2011]染色 Time Limit: 20 Sec Memory Limit: 512 MBSubmit: 5020 Solved: 1872[Submit][Status ...
- Hdu 3966-Aragorn's Story LCT,动态树
题目:http://acm.hdu.edu.cn/showproblem.php?pid=3966 Aragorn's Story Time Limit: 10000/3000 MS (Java/Ot ...
- Hdu 4010-Query on The Trees LCT,动态树
Query on The Trees Time Limit: 10000/5000 MS (Java/Others) Memory Limit: 65768/65768 K (Java/Othe ...
- HDU4010 Query on The Trees (LCT动态树)
Query on The Trees Time Limit: 10000/5000 MS (Java/Others) Memory Limit: 65768/65768 K (Java/Othe ...
- Hdu 2475-Box LCT,动态树
Box Time Limit: 10000/5000 MS (Java/Others) Memory Limit: 32768/32768 K (Java/Others)Total Submis ...
随机推荐
- 所谓的液晶屏驱动IC是单独的IC还是在屏内就集成
所谓的液晶屏驱动IC是单独的IC还是在屏内就集成 时间:2016-12-05 作者:admin 其实无论什么液晶屏,想要正常工作必须包括两个人:玻璃屏+驱动IC:但是现在有一些液晶厂商他们不 ...
- 让win7变成无线路由(需要用管理员权限打开)最后完善.rar
让win7变成无线路由(需要用管理员权限打开)最后完善.bat @ECHO OFF CLS color 0a netsh wlan show drivers ECHO.★★★★★★★★★★★★★★★★ ...
- android环境的搭配
android环境一般采用的是adt bundle 下载地址如下: http://tools.android-studio.org/index.php/adt-bundle-plugin 根据自己jd ...
- Cloud Container Service experimentation
Cloud Container Service experimentation K8S技术社区 举办云容器技术动手工作坊 活动时间:2018年1月13日(周六)13:30-17:30 活动地点:北京海 ...
- vs编译器好多下划波浪线但不报错
解决办法:项目属性->c/c++->常规->附加包含目录->$(ProjectDir): $(ProjectDir) 项目的目录(定义形式:驱动器 + 路径):包括尾部的反斜杠 ...
- 蓝牙inquiry流程之HCI_Inquiry_Result_With_RSSI和HCI Extended Inquiry Result处理
首先介绍一下和inquiry的相关的流程. inquiry是从协议栈下发的一个HCI命令.其格式如下: 这里简单介绍下第二个参数,是inquiry的持续时间, 从上图看出 inquiry持续的时间是 ...
- JQuery快速入门-事件与效果
一.事件 事件绑定的方法有两种: 绑定到元素 查找元素后绑定事件 方法1:绑定到元素 <body> <p onclick='func1()'>点击我</p> < ...
- 虚拟机virtualBox安装linux系统 xshell远程连接linux
虚拟机virtualBox安装linux系统 xshell远程连接linux 虚拟机概念: 通过软件, 使用虚拟化技术虚拟出电脑的硬件环境, 充当真实的电脑使用. 常见的虚拟软件: virtualBo ...
- MIT-6.824 MapReduce
概述 MapReduce是由JeffreyDean提出的一种处理大数据的编程模型,用户定义map和reduce函数,map函数处理原始数据生成一系列键值对中间数据,reduce函数并合相同key的键值 ...
- Redis学习01_redis安装部署(centos)
原文: http://www.cnblogs.com/herblog/p/9305668.html Redis学习(一):CentOS下redis安装和部署 1.基础知识 redis是用C语言开发的 ...