首页 > 其他分享 >数据结构学习笔记

数据结构学习笔记

时间:2024-08-27 21:08:34浏览次数:9  
标签:Splay int mid 笔记 son 学习 fa 数据结构 id

李超线段树学习笔记

模板传送门

从模板题就能看出来嗷,李超线段树非常牛逼。\bx

从名字中就能看出来嗷,这玩意儿是个线段树。

那么考虑在线段树上维护一堆线(一次函数)。

对于每个点,存所有线中,使这个线段 $ mid $ 的点的线。

对于加入一个点,根节点递归,扫到一个点时,若这个点在 $ mid $ 时大于当前最优线,就将这个线段上的最优线替换。

对于递归左右子节点,若左端点中,这个点比最优先段优,那么直接递归。否则

  • 这个线不可以作为左儿子的最优线。一点也不遗憾没有递归,很好!

  • 这个线可以作为左儿子的最优线。有点遗憾没有递归,但是显然这个线已经作为了这个点的最优线,从而使得无需递归。不遗憾了

右端点同理。那么这玩意儿就很合理的更新了。(动态开点)代码

void updata(int& x, int i, int L = -2e8, int R = 2e8)
{
	if (!x) x = ++idx;
	if (!id[x]) return id[x] = i, void();
	int mid = L + R >> 1;
	if (f[i](mid) > f[id[x]](mid)) swap(i, id[x]);
	if (L == R) return;
	if (f[i](L) > f[id[x]](L)) updata(l[x], i, L, mid);
	if (f[i](R) > f[id[x]](R)) updata(r[x], i, mid + 1, R);
}

对于查询,直接递归即可。全部代码

namespace LCST  //Li Chao Segment Tree
{
	struct Function
	{
		int a, b;
		int operator () (int x) { return a * x + b; }
	};
	Function f[N];
	int fidx;
	int id[N << 5];
	int l[N << 5];
	int r[N << 5];
	int idx = 1;
	int root = 1;
	void updata(int& x, int i, int L = -2e8, int R = 2e8)
	{
		if (!x) x = ++idx;
		if (!id[x]) return id[x] = i, void();
		int mid = L + R >> 1;
		if (f[i](mid) > f[id[x]](mid)) swap(i, id[x]);
		if (L == R) return;
		if (f[i](L) > f[id[x]](L)) updata(l[x], i, L, mid);
		if (f[i](R) > f[id[x]](R)) updata(r[x], i, mid + 1, R);
		return;
	}
	int query(int x, int k, int L = -2e8, int R = 2e8)
	{
		int res = 0;
		if (id[x]) res = f[id[x]](k);
		if (L == R) return res;
		int mid = L + R >> 1;
		if (k <= mid) res = max(res, query(l[x], k, L, mid));
		else res = max(res, query(r[x], k, mid + 1, R));
		return res;
	}
	inline void build()				//init
	{
		for (int i = 1; i <= idx; i++) l[i] = r[i] = id[i] = 0;
		idx = root = 1;
	}
	inline void add(int a, int b)	//add f(x)=ax+b
	{
		f[++fidx] = { a, b };
		updata(root, fidx);
	}
	inline int query(int k)			//query max f(k)
	{
		return query(1, k);
	}
}

Link-Cut-Tree学习笔记

对于一棵树,实链剖分,对每条链建立 Splay,这就是Link-Cut-Tree 的主要思想。

Rotate(x)和Splay(x)

和普通 Splay 有一点点不一样。

inline bool isroot(int x) { return (son[fa[x]][0] != x && son[fa[x]][1] != x); }
inline void uppushdown(int x) { if (!isroot(x)) uppushdown(fa[x]); pushdown(x); }
inline bool get(int x) { return x == son[fa[x]][1]; }
inline void rotate(int x)
{
	int p = fa[x], q = fa[p]; bool chk = get(x);
	if (!isroot(p)) son[q][get(p)] = x;
	son[p][chk] = son[x][chk ^ 1];
	fa[son[x][chk ^ 1]] = p;
	son[x][chk ^ 1] = p;
	fa[p] = x, fa[x] = q;
	maintain(p), maintain(x);
}
inline void Splay(int x)
{
	uppushdown(x);
	for (int f = fa[x]; f = fa[x], !isroot(x); rotate(x)) if (!isroot(f)) rotate(get(x) == get(f) ? f : x);
}

Access(x)

使 $ x $ 与根节点在同一条实链上(且 $ x $ 为路径的尾端)

按含义模拟即可。

inline int Access(int x)
{
	for (int s = 0; x; s = x, x = fa[x])
	{
		Splay(x);
		son[x][1] = s;
		maintain(x);
	}
	return s;
}

最后的返回值为辅助树的根节点。

Makeroot(x)

使 $ x $ 作为原树的根。

Access(x), Splay(x),让 $ x $ 为辅助树树的根。然后对于这条链来说,反转就是将链反转,Splay打上旋转标记即可。即reverse(x)

或者 reverse(Access(x)),也可以,但是好像多 Splay() 能保证复杂度。

inline void makeroot(int x)
{
	Access(x), Splay(x), reverse(x);
}

Findroot(x)

找到 $ x $ 原树的根。

很普通,按含义模拟即可

inline int findroot(int x)
{
	Access(x);
	Splay(x);
	pushdown(x);
	while (son[x][0]) x = son[x][0], pushdown(x);
	Splay(x);
	return x;
}

Split(x, y)

将 $ x $ 到 $ y $ 的路径抽到一条链上。

Makeroot(x), Access(y) 就好了,再 Splay(y) 一下,$ x $ 到 $ y $ 的路径就在 $ y $ 的子树里了,操作查询直接对 $ y $ 的子树查/改即可。

inline void split(int x, int y)
{
	makeroot(x), Access(y), Splay(y);
}

Link(x, y)

连接 $ x, y $。

终于来了,连接的话 makeroot(x) 使 $ x $ 为原树和辅助树的根,然后 $ x $ 向 $ y $ 连一条虚边即可。

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

Cut(x, y)

断开 $ x, y $ 的边。

Split(x, y),这时 $ x $ 一定是 $ y $ 的左儿子,且两个点构成一颗 Splay,两点双向断开即可。

inline void cut(int x, int y)
{
	split(x, y);
	fa[x] = son[y][0] = 0;
	maintain(y);
}

总结

LCT的操作比较灵活,一般只要写的合理,跟别人写的不一样也是珂以的。

标签:Splay,int,mid,笔记,son,学习,fa,数据结构,id
From: https://www.cnblogs.com/xieruyu666/p/18383446

相关文章

  • 前后端开发学习路线 囊括Dubbo、Elasticsearch等
    以下都是博主本人看过后给出的推荐。文章目录前端入门Web开发基础(HTML、CSS、JS)写项目前置(AJAX、Vue等)开始写项目(Vue、Uniapp)重点Future入门Java后端基础部分(Java、MySQL)JavaMySQL正道邪道写项目前置(JavaWeb的基础认识)开始写项目(SpringBoot、Redis等)重点Future后......
  • C++系列学习笔记
    #include<iostream>#include<iomanip>usingnamespacestd;//namespace:命名空间的关键字//std:系统的关键字intmain(){cout<<"输入"<<endl<<"int,char,double"<<endl;intnum=0;ch......
  • NoteLLM论文阅读笔记
    NoteLLM:ARetrievableLargeLanguageModelforNoteRecommendation论文阅读笔记Abstract存在的问题:​ 现有的在线方法只是将笔记输入基于BERT的模型,生成用于评估相似性的笔记嵌入。然而,它们可能没有充分利用一些重要的线索,例如代表笔记关键概念的标签或类别。事实上,学习......
  • 笔记——字符串
    蓝月の笔记——字符串篇摘要一些串串\(\quad\qquad\)——某yl新高一学长字串\(\quad\qquad\)——某yl新高一学长のpptWarning本文中字符串的下标有时从\(1\)开始有时从\(0\)开始,请自行分辨无特殊说明从\(1\)开始字符串长度无特殊说明为\(n\)字符串无特殊说明表示......
  • CMake构建学习笔记8-OpenSceneGraph库的构建
    1.概论在连续构建了zlib、libpng、libjpeg、libtiff、giflib以及freetype这几个库之后,接下来我们就要来一个大的,构建OpenSceneGraph这样大型库。OpenSceneGraph(简称OSG)是一个高性能、跨平台的三维图形应用程序框架,广泛应用于科学可视化、模拟仿真、游戏开发等领域。理论上来说,......
  • Vue3的学习---10
    10.Vuex10.1Vuex简介10.1.1Vuex概述Vuex是Vue.js应用程序的状态管理模式+库。它作为中央存储库,用于管理应用程序中所有组件的状态,并以可预测的方式进行状态变更。Vuex的设计理念是基于Flux架构,主要由以下几个核心概念组成:State(状态):存储应用程序的所有状态数据。......
  • 读书笔记(7)语录收集
    序言1.Onepictureisworthathousandwords.千言不如一画2.Ifyougivesomeoneaprogram,youwillfrustratethemforaday;ifyouteachthemhowtoprogram,youwillfrustratethemforalifetime.(如果你交给某人一个程序,你将折磨他一整天;如果你教某人如何编写......
  • IDA反汇编STM32代码学习记录
    首先,使用IDA反汇编STM32代码应该打开的是bin文件,而不是.hex或.axf文件,只有bin文件是和下载到flash内的数据一致的。具体参见:三种文件的区别那么,怎么生成bin文件呢,在有工程的情况下,在MDK中是在user的afterbuild后添加命令:fromelf--bin-o./Output/@L.bin./Output/@L.axf@L代......
  • [Jsprit]Jsprit学习笔记-一个简单的示例
    学习官网提供的例子示例代码publicclassSimpleExample{publicstaticvoidmain(String[]args){/**somepreparation-createoutputfolder */Filedir=newFile("output");//ifthedirectorydoesnotexist,......
  • 给自己复盘用的tjxt笔记day10
    领取优惠券开发流程页面原型分析,接口统计,数据库设计,生成代码,引入枚举状态接口开发查询发放中的优惠券根据页面原型和接口分析和前端设计的要求,获得四要素@OverridepublicList<CouponVO>queryIssuingCoupons(){//1.查询发放中的优惠券列表List<Coupon>......