模板汇总——LCT
link-cut tree
#define lch(x) tr[x].son[0]
#define rch(x) tr[x].son[1]
const int N = 5e5 + ;
struct Node{
int rev, rt;
int son[], pre;
int mx, val, id;
void init(){
rt = ; rev = pre = son[] = son[] = ;
mx = val = id = ;
}
}tr[N];
void Push_Rev(int x){
if(!x) return ;
swap(lch(x), rch(x));
tr[x].rev ^= ;
}
void Push_Up(int x){
if(!x) return ;
tr[x].mx = tr[x].val, tr[x].id = x;
if(tr[x].mx < tr[lch(x)].mx) tr[x].mx = tr[lch(x)].mx, tr[x].id = tr[lch(x)].id;
if(tr[x].mx < tr[rch(x)].mx) tr[x].mx = tr[rch(x)].mx, tr[x].id = tr[rch(x)].id;
}
void Push_Down(int x){
if(tr[x].rev){
tr[x].rev = ;
Push_Rev(lch(x));
Push_Rev(rch(x));
}
}
void Rev(int x){
if(!tr[x].rt) Rev(tr[x].pre);
Push_Down(x);
}
void rotate(int x){
if(tr[x].rt) return;
int y = tr[x].pre, z = tr[y].pre;
int k = (rch(y) == x);
tr[y].son[k] = tr[x].son[k^];
tr[tr[y].son[k]].pre = y;
tr[x].son[k^] = y;
tr[y].pre = x;
tr[x].pre = z;
if(tr[y].rt) tr[y].rt = , tr[x].rt = ;
else tr[z].son[rch(z) == y] = x;
Push_Up(y);
}
void Splay(int x){
Rev(x);
while(!tr[x].rt){
int y = tr[x].pre, z = tr[y].pre;
if(!tr[y].rt){
if(( x == rch(y) ) != (y == rch(z))) rotate(x);
else rotate(y);
}
rotate(x);
}
Push_Up(x);
}
void Access(int x){
int y = ;
do{
Splay(x);
tr[rch(x)].rt = ;
rch(x) = y;
tr[y].rt = ;
Push_Up(x);
y = x;
x = tr[x].pre;
}while(x);
}
void Make_rt(int x){
Access(x);
Splay(x);
Push_Rev(x);
}
bool judge(int u, int v){
while(tr[u].pre) u = tr[u].pre;
while(tr[v].pre) v = tr[v].pre;
return u == v;
}
void link(int u, int v){
Make_rt(u);
tr[u].pre = v;
}
void cut(int u, int v){
Make_rt(u);
Access(v);
Splay(v);
tr[lch(v)].pre = ;
tr[lch(v)].rt = ;
tr[v].pre = ;
lch(v) = ;
}
维护子树。
维护子树就是新开一个状态存一下 所有非偏爱子节点的信息, 然后每次access的时候我们就根据偏爱子节点的变化, 从而更新这个新开的状态。
这个写法 是维护 子树内的亦或和。
代码:
#define lch(x) tr[x].son[0]
#define rch(x) tr[x].son[1]
const int N = 5e5 + ;
struct Node{
int rev, rt;
int son[], pre;
int sum, vsum, key;
void init(){
rt = ; rev = pre = son[] = son[] = ;
sum = vsum = key = ;
}
}tr[N];
void Push_Rev(int x){
if(!x) return ;
swap(lch(x), rch(x));
tr[x].rev ^= ;
}
void Push_Up(int x){
if(!x) return ;
tr[x].sum = tr[x].key ^ tr[lch(x)].sum ^ tr[rch(x)].sum ^ tr[x].vsum;
}
void Push_Down(int x){
if(tr[x].rev){
tr[x].rev = ;
Push_Rev(lch(x));
Push_Rev(rch(x));
}
}
void Rev(int x){
if(!tr[x].rt) Rev(tr[x].pre);
Push_Down(x);
}
void rotate(int x){
if(tr[x].rt) return;
int y = tr[x].pre, z = tr[y].pre;
int k = (rch(y) == x);
tr[y].son[k] = tr[x].son[k^];
tr[tr[y].son[k]].pre = y;
tr[x].son[k^] = y;
tr[y].pre = x;
tr[x].pre = z;
if(tr[y].rt) tr[y].rt = , tr[x].rt = ;
else tr[z].son[rch(z) == y] = x;
Push_Up(y);
}
void Splay(int x){
Rev(x);
while(!tr[x].rt){
int y = tr[x].pre, z = tr[y].pre;
if(!tr[y].rt){
if(( x == rch(y) ) != (y == rch(z))) rotate(x);
else rotate(y);
}
rotate(x);
}
Push_Up(x);
}
void Access(int x){
int y = ;
do{
Splay(x);
tr[rch(x)].rt = ;
tr[x].vsum ^= tr[rch(x)].sum;
rch(x) = y;
tr[x].vsum ^= tr[rch(x)].sum;
tr[y].rt = ;
Push_Up(x);
y = x;
x = tr[x].pre;
}while(x);
}
void Make_rt(int x){
Access(x);
Splay(x);
Push_Rev(x);
}
void link(int u, int v){
Make_rt(u);
Access(v);
Splay(v);
tr[u].pre = v;
tr[v].
vsum ^= tr[u].sum;
Push_Up(v);
}
void cut(int u, int v){
Make_rt(u);
Access(v);
Splay(v);
tr[lch(v)].pre = ;
tr[lch(v)].rt = ;
tr[v].pre = ;
lch(v) = ;
Push_Up(v);
}
模板汇总——LCT的更多相关文章
- 模板—数据结构—LCT
模板—数据结构—LCT Code: #include <cstdio> #include <algorithm> using namespace std; #define N ...
- 单元最短路径算法模板汇总(Dijkstra, BF,SPFA),附链式前向星模板
一:dijkstra算法时间复杂度,用优先级队列优化的话,O((M+N)logN)求单源最短路径,要求所有边的权值非负.若图中出现权值为负的边,Dijkstra算法就会失效,求出的最短路径就可能是错的 ...
- link cut tree模板(LCT模板)
update:2017.09.26 #include <bits/stdc++.h> using namespace std; struct Link_Cut_Tree { + ; ], ...
- 【模板】NOIP模板汇总
图论 数据结构 数学 其他: 洛谷模板:a,b两个字符串,求b串在a串中出现的位置 #include<iostream> #include<cstdio> #include&l ...
- 模板汇总——KMP & EX-KMP
1. kmp 相当于往前求出一段字符信息,使得 这段字符信息和前缀相等. void getnext(){ , j = ; nx[] = -; while(j < m){ || b[j] == b ...
- 模板汇总——AC自动机
AC自动机 模板题 HDU-2222 Keywords Search #include<bits/stdc++.h> using namespace std; #define LL lon ...
- 【模板】LCT
核心思想: 动态维护一个森林.支持删边,加边,查询链信息等很多操作. 由若干棵$Splay$组成,每棵$Splay$维护一条链,以深度作为关键字. 也就是说$Splay$的中序遍历相当于从上到下遍历这 ...
- python实现AES/DES/RSA/MD5/SM2/SM4/3DES加密算法模板汇总
都是作者累积的,且看其珍惜,大家可以尽量可以保存一下,如果转载请写好出处https://www.cnblogs.com/pythonywy 一.md5加密 1.简介 这是一种使用非常广泛的加密方式,不 ...
- 【POJ各种模板汇总】(写在逆风省选前)(不断更新中)
1.POJ1258 水水的prim……不过poj上硬是没过,wikioi上的原题却过了 #include<cstring> #include<algorithm> #inclu ...
随机推荐
- 100天搞定机器学习|Day13-14 SVM的实现
昨天我们学习了支持向量机基本概念,重申数学推导原理的重要性并向大家介绍了一篇非常不错的文章.今天,我们使用Scikit-Learn中的SVC分类器实现SVM.我们将在day16使用kernel-tri ...
- PPT | Docker定义存储-让应用无痛运行
编者注: 本文为9月27日晚上8点有容云平台存储架构师张朝潞在腾讯课堂中演讲的PPT,本次课堂为有容云主办的线上直播Docker Live时代●Online Meetup-第三期:Docker定义存储 ...
- 如何选择合适的SSL证书类型
网站安装SSL证书就可以将http升级为https加密模式,网站安装SSL证书因此成为一种趋势.如何为网站选择适合的SSL证书类型呢? SSL证书类型可分为2大类:1)按照验证方式分类2)按照支持域名 ...
- 图像反转(一些基本的灰度变换函数)基本原理及Python实现
1. 基本原理 获取像素值在[0, L]范围内的图像的反转图像,即为负片.适用于增强图像中白色或者灰色的区域,尤其当黑色在图片中占主地位时候 $$T(r) = L-r$$ 2. 运行结果 图源自ski ...
- javascript 异步请求封装成同步请求
此方法是异步请求封装成同步请求,加上token验证,环境试用微信小程序,可以修改文件中的ajax,进行封装自己的,比如用axios等 成功码采用标准的 200 到 300 和304 ,需要可以自行修改 ...
- 扩展欧几里德算法(递归及非递归实现c++版)
今天终于弄懂了扩展欧几里德算法,有了自己的理解,觉得很神奇,就想着写一篇博客. 在介绍扩展欧几里德算法之前,我们先来回顾一下欧几里德算法. 欧几里德算法(辗转相除法): 辗转相除法求最大公约数,高中就 ...
- Mac安装Homebrew的那些事儿
Mac安装Homebrew的那些事儿 最近小明刚换置了一个 Mac 本,想搭建一个属于自己的博客网站,需要用到 Node.js 环境,而Node.js 在 MacOS 中是由 Homebrew 进行安 ...
- dubbokeeper-moniter部署指南
moniter在整个dubbo架构中的角色: 使用的1.0.1版本: ## 1.0.1版本变动内容 dubbokeeper在1.0.1版本对监控数据存储模块抽离出来,做为单独的应用部署,而不是和1.0 ...
- javaweb基础整理随笔-----上传与下载步骤详解
这次整理的是上传与下载的原生代码解析: 上传:1.对页面的要求:enctype="multipart/form-data" method="post" ...
- 前端模板引擎doT.js的用法
简介 一款简单好用的前端模板引擎 用法 <script type="text/javascript" src="js/doT.min.js">< ...