首页 > 其他分享 >2.6-2.7

2.6-2.7

时间:2023-02-07 10:33:17浏览次数:104  
标签:access ch int void splay fa 2.7 2.6

Link Cut Tree(动态树)

概念讲解

LCT维护的对象其实是一个森林。
在实链剖分的基础下,LCT支持更多的操作,即树剖升级版,但在实际做题中因为树剖的常数小且相对容易调试,所以能用树剖就尽量用树剖。

  1. 查询、修改链上的信息(最值,总和,异或和等)
  2. 随意指定原树的根(即换根)
  3. 动态连边、删边
  4. 合并两棵树、分离一棵树(跟上面不是一毛一样吗)
  5. 动态维护连通性
  6. 更多操作

操作

access(x)

作用: 把从根到 x 的所有点放在一条实链里,使根到 x 成为一条实路径,并且在同一棵 Splay 里

代码实现:(循环处理)

  1. 转到根
  2. 换儿子
  3. 更新信息
  4. 操作点切换为轻边所指的父亲,然后进行操作1
void access(int x){
	for(int y=0;x;y=x,x=fa[x]){
		splay(x);
		ch[x][1]=y;
		updat(y);
	}
}

makeroot(x)

作用:使 x 点成为其所在树的根

void makeroot(int x){
	access(x);
	splay(x);
	reverse(x);
}

split(x,y)

作用:提取出 x, y 间的路径,方便做区间操作

void split(int x,int y){
	makeroot(x);
	access(y);
	splay(y);
}

link(x,y)

作用:在 x, y 两点间连一条边

void link(int x,int y){
	makeroot(x);
	fa[x]=y;
}

cut(x,y)

作用:把 x, y 两点间边删掉

void cut(int x,int y){
	split(x,y);
	if(ch[y][0]!=x||ch[x][1])return ;
	fa[x]=ch[y][0]=0;
	updat(y);
}

findroot(x)

作用:找到 x 所在树的根节点编号

int findroot(int x){
	access(x);
	splay(x);
	while(ch[x][0])pushdown(x),x=ch[x][0];
	splay(x);
	return x;
}

模板:洛谷P3690

模板代码
#include<bits/stdc++.h>
using namespace std;
const int N=3e5+5;
struct node {
	int fa,ch[2],sum,val,lazy;
} t[N];    //lazy用来标记reverse()的左右翻转
#define lc t[x].ch[0]    //左儿子
#define rc t[x].ch[1]    //右儿子
bool isRoot(int x) {     //判断是否是splay根节点
	int g=t[x].fa;
	return t[g].ch[0]!=x && t[g].ch[1]!=x;//若为根,则父结点不应该有这个儿子
}
void pushup(int x) {     //本题的求路径异或和。上传信息
	t[x].sum=t[x].val^t[lc].sum^t[rc].sum;
}
void reverse(int x) {
	if(!x)return;
	swap(lc,rc);         //翻转x的左右儿子
	t[x].lazy^=1;        //懒惰标记,先不翻转儿子的后代,后面再翻转
}
void pushdown(int x) {   //递归翻转x的儿子的后代,并释放懒标记。
	if(t[x].lazy) {
		reverse(lc);
		reverse(rc);
		t[x].lazy=0;
	}
}
void push(int x) {
	if(!isRoot(x))  push(t[x].fa);  //从根到x全部pushdown
	pushdown(x);
}
void rotate(int x) {
	int y=t[x].fa;
	int z=t[y].fa;
	int k=t[y].ch[1]==x;
	if(!isRoot(y)) t[z].ch[t[z].ch[1]==y]=x;//这里要稍微注意 
	t[x].fa=z;
	t[y].ch[k]=t[x].ch[k^1];
	if(t[x].ch[k^1])t[t[x].ch[k^1]].fa=y;
	t[y].fa=x;
	t[x].ch[k^1]=y;
	pushup(y);
}
void splay(int x) {    //提根:把x旋转为它所在的Splay树的根
	int y,z;
	push(x);           //先pushdown处理x的所有子孙的lazy标记
	while(!isRoot(x)) {
		y=t[x].fa,z=t[y].fa;
		if(!isRoot(y))
			(t[z].ch[0]==y)^(t[y].ch[0]==x)?rotate(x):rotate(y);
		rotate(x);
	}
	pushup(x);
}
void access(int x) {   //在原树上建一条实链,起点是根,终点是x
	for(int child=0; x; child=x, x=t[x].fa) { //从x往上走,沿着虚边走到根
		splay(x);
		rc = child;     //右孩子是child,建立了一条实边
		pushup(x);//路径信息处理 
		if(child) t[child].fa=x;
	}
}
void makeroot(int x) { //把x在原树上旋转到根的位置
	//使节点x成为原树树根,该操作等价于将“根节点到节点x”路径上所有树边的方向取反 
	access(x);
	splay(x);
	reverse(x);//在原树发生变化 
}
void split(int x,int y) {  //把原树上以x为起点、y为终点的路径,生成一条实链
	makeroot(x);
	access(y);
	splay(y);
}
void link(int x,int y) {  //在结点x和y之间连接一条边
	makeroot(x);
	t[x].fa=y;
}
void cut(int x,int y) { //将x,y的边切断
	split(x,y);
	if(t[y].ch[0]!=x||rc)  return;
	t[x].fa=t[y].ch[0]=0;
	pushup(y);
}
int findroot(int x) { //查找x在原树上的根,也可以直接判断两点的连通性。 
	access(x);
	splay(x);
	while(lc)  pushdown(x),x=lc;    //找Splay树最左端的结点
	return x;
}
int main() {
	int n,m;
	scanf("%d%d",&n,&m);
	for(int i=1; i<=n; ++i) {
		scanf("%d",&t[i].val);
		t[i].sum = t[i].val;
	}
	while(m--) {
		int opt,a,b;
		scanf("%d%d%d",&opt,&a,&b);
		switch(opt) {
			case 0:
				split(a,b);
				printf("%d\n",t[b].sum);
				break;
			case 1:
				if(findroot(a) != findroot(b)) link(a,b);
				break;
			case 2:
				cut(a,b);
				break;
			case 3:
				splay(a);
				t[a].val=b;
				break;
		}
	}
	return 0;
}

讲的比较好的博客

大佬的题单

我的[题单]

标签:access,ch,int,void,splay,fa,2.7,2.6
From: https://www.cnblogs.com/mkik/p/17095534.html

相关文章

  • 闲话 23.2.6
    闲话?感觉没啥想说的诶但是jjdw请勿宣称一些不存在的辈分关系......
  • 2023.2.6 日寄
    2023.2.6日寄一言\(~~~~\)人生海海,潮落之后是潮起。你说那是消磨、笑柄、罪过,可那就是我的英雄主义。——麦家模拟赛ClickHere鲜花\(~~~~\)今天和同学去食......
  • python2.7 + MySQL 拼接SQL语句的技巧 (处理unicode,时间)
    背景在Python2.7中,可以使用单引号,双引号,三引号表示字符串,当字符串的值为中文时,则会默认转换成unicode。但是在MYSQL中,使用SQL语句时,直接用unicode作为列的查询条件(例如......
  • spring boot 2.6.2解决log4j漏洞
    公司版本2.3,因为那个log4j漏洞准备升级2.6.2测试下,记录下出现的问题高版本不允许循环依赖,如果写的时候不太注意,改的时候也要改很多地方,最后决定添加个配置解决在bootstra......
  • web之php一句话木马总结------2023.2.6
    一句话木马的原理<?php@eval($_POST['shell']);?>这是php的一句话后门中最普遍的一种。它的工作原理是:首先存在一个名为shell的变量,shell的取值为HTTP的POST方式。Web......
  • web之命令执行常见函数------2023.2.6
     system()函数作用:将字符串作为OS命令执行,自带输出功能。格式:stringsystem(string$command[,int&$return_var])//$command为执行的命令,&return_var可选,用来......
  • Dubbo2.7的Dubbo SPI实现原理细节
    总结/朱季谦本文主要记录我对DubboSPI实现原理的理解,至于什么是SPI,我这里就不像其他博文一样详细地从概念再到JavaSPI细细分析了,直接开门见山来分享我对DubboSPI的见解......
  • 2.6掌握逻辑运算的窍门
    将二进制数表示的信息作为四则运算的数值来处理就是算术。而像图形模式那样,将数值处理为单纯的0和1的罗列就是逻辑。计算机能处理的运算,大体可分为算术运算和逻辑运算。算......
  • saber 2.7.1 maven 配置
    私服2.7.1旧版本失效,加载maven本地jar包  ......
  • 简谈源码-Picasso(v2.71828)
    概述:设计模式用到单例和建造者;网络请求使用OkHttp3;缓存算法使用LRU;线程切换使用Handler​​Picasso官网​​Picasso.get().load(url).into(iv);Picasso的常见使用步骤很简单......