学习LCT小结

前前言

话说前面部分大概是我一年前搞的吧。
最近又复习了一哈LCT,那就补补坑吧。
注意,为了区分,从我写spaly开始都是现在写的。

前言

首先,LCT是什么呢?
我们看看百度百科——

LCT即自动细胞学检测系统,又称液基细胞学检测系统。是宫颈筛查的一种方法。

疏松结缔组织(loose connective tissue)又称蜂窝组织(areolar tissue),其特点是细胞种类较多,纤维较少,排列稀疏。疏松结缔组织在体内广泛分布,位于器官之间、组织之间以至细胞之间,起连接、支持、营养、防御、保护和创伤修复等功能。

好吧,不是这个。
LCT即为link-cut-tree
是一种解决动态树的有效利器。
动态树是一类问题,常见的有维护树的连通性,求树上路径的极值等。

然后LCT即为一种用Splay来维护树链剖分的算法,简单理解为“支持删边、加边的动态树链剖分”

前置技能:

树链剖分https://blog.youkuaiyun.com/HiChocolate/article/details/77170675
(不会的可以看看我写的)
Splay https://blog.youkuaiyun.com/qq_30974369/article/details/77587168
(不会的可以看看不是我写的)
重点是树链剖分的全部内容加上splay的一些基本操作(如标记下传、区间翻转《排序机械臂》)

一些定义

既然百度百科没有很好的定义来学习,那我就来大致讲讲。(实际上是我懒得打定义)

LCT的本质也是树链剖分,它的树也是用很多的偏爱路径和非偏爱路径来连接起来的。
这些为了方便理解,不妨也用树链剖分的定义来定义。
1、重边连起来会组成重链,重链之间没有公共点。
我们首先跑一遍算出dfn序之后,我们就可以找到很多很多条重链。
2、那么对于一颗树,其中一条重链的点,都在一颗splay中,关键字是深度。
3、树链剖分的重链是一成不变的,但是LCT的重链是可以随意改变的。这也注定了LCT的重链需要用到splay来维护。
4、重链与重链之间的边在splay中用虚边来表示。
5、一条重链的虚边会存在它的splay的根上,指向这条重链的顶点的father所在的重链的splay的根。

就是这么多啦。
其实这样子很难理解4与5的定义什么意思,那么我们画画图。
这里写图片描述
上面加粗的边即为重边,然后连成重链。
然后,我们把每一条重链都给弄出来,对它建一颗splay,那么就变成——
这里写图片描述
那么对于上面的这个图,三角形就代表一个splay,每个splay对应着LCT上的每个链。
那么有些链是用一条轻边连起来的,那么在splay上就用一个虚边连接。
理解定义5,就会发现在这张图上,这些有向边可以表示为虚边。

然后就大致介绍完LCT的基本定义与构造了。

一些干货

由于我们的这个LCT并不需要把它建出来,只需要维护spaly即可。
因此,我们节点维护下面的一些基本值:

  • fa表示当前节点spaly上的父亲
  • pf表示当前节点在LCT上虚边连接的点
  • son[1/0]在spaly上的儿子

关于spaly

其实spaly在LCT中只需要利用其旋转,就可以基本完成一切操作(废话)
那么在旋转过程中,需要改进的只有一个向虚边传送。
代码

void rotate(int x)
{
    int y=t[x].fa,k=get(x);
    if(t[y].fa) t[t[y].fa].son[get(y)]=x;
    if(t[x].son[!k]) t[t[x].son[!k]].fa=y;
    t[y].son[k]=t[x].son[!k],t[x].fa=t[y].fa,t[y].fa=x,t[x].son[!k]=y;
    update(y),update(x);
    t[x].pf=t[y].pf;//就在这里!!!
}

核心操作access

我们定义一个操作\(access(x)\)表示把当前x到根的所有边都变成重边,然后把这条链以外的所以边变成轻边。
具体操作看图:
(盗盗图)
在这里插入图片描述
应该很好理解。
代码:

void access(int x)
{
    for (int y=0;x;update(x),y=x,x=t[x].pf)//一直跳重链
    {
        splay(x,0);
        t[t[x].son[1]].fa=0;//断掉原来的重链
        t[t[x].son[1]].pf=x;
        t[x].son[1]=y;//把下面的spaly接到上面
        t[y].fa=x;
        t[y].pf=0;
    }
}

基本操作1 makeroot

我们定义一个操作\(makeroots(x)\)表示把x变成LCT的根。
操作简单,先access一下,那么我们就可以得到一颗spaly。
然鹅这颗spaly最右边的点是x,我们要把他变成最左边。
于是把它旋转到根,翻转一下即可(翻转就是排序机械臂中的翻转)
代码:

void make(int x)
{
    swap(t[x].son[0],t[x].son[1]);
    t[x].tag^=1;
}
void makeroot(int x)
{
    access(x),splay(x,0);
    make(x);
}

基本操作2 findroot

我们定义一个操作\(findroots(x)\)表示寻找x所在树的root。
这个操作有什么用呢?
你可以用这个代替并查集,只是时间多了些
用醋很多,就不一一介绍了。

如何实现?
access(x)一下,然后我们发现x和原本的根在同一spaly上。
然后询问spaly上最左边的点即可。

int findroot(int x)
{
    access(x),splay(x,0);
    for (;t[x].son[0];x=t[x].son[0]);
    return x;
}

这个就很帅气了。
我们定义一个操作\(link(x,y)\)表示连接x和y这条边。
方法很简单,我们先makeroot(x),然后把x连接到y即可。

void link(int x,int y)
{
    makeroot(x);
    if(findroot(y)!=x) t[x].pf=y;
}

基本操作4 cut

我们定义一个操作\(cut(x,y)\)表示删掉x和y这条边。
我们考虑makeroot(x),然后access(y)。
如果x和y之间有连边,那么y必定是x的儿子。
断掉即可。

void cut(int x,int y)
{
    makeroot(x),access(y),splay(y,0);
    if(t[x].fa==y) t[y].son[get(x)]=t[x].fa=t[x].pf=0;
}

应用

大致就是上面的这些操作。
例题?洛谷上很多。
当然,https://blog.youkuaiyun.com/HiChocolate/article/details/101380259
这也是一个模板。

转载于:https://www.cnblogs.com/RainbowCrown/p/11600799.html

需求响应动态冰蓄冷系统与需求响应策略的优化研究(Matlab代码实现)内容概要:本文围绕需求响应动态冰蓄冷系统及其优化策略展开研究,结合Matlab代码实现,探讨了在电力需求侧管理背景下,冰蓄冷系统如何通过优化运行策略参与需求响应,以实现削峰填谷、降低用电成本和提升能源利用效率的目标。研究内容包括系统建模、负荷预测、优化算法设计(如智能优化算法)以及多场景仿真验证,重点分析不同需求响应机制下系统的经济性和运行特性,并通过Matlab编程实现模型求解与结果可视化,为实际工程应用提供理论支持和技术路径。; 适合人群:具备一定电力系统、能源工程或自动化背景的研究生、科研人员及从事综合能源系统优化工作的工程师;熟悉Matlab编程且对需求响应、储能优化等领域感兴趣的技术人员。; 使用场景及目标:①用于高校科研中关于冰蓄冷系统与需求响应协同优化的课题研究;②支撑企业开展楼宇能源管理系统、智慧园区调度平台的设计与仿真;③为政策制定者评估需求响应措施的有效性提供量化分析工具。; 阅读建议:建议读者结合文中Matlab代码逐段理解模型构建与算法实现过程,重点关注目标函数设定、约束条件处理及优化结果分析部分,同时可拓展应用其他智能算法进行对比实验,加深对系统优化机制的理解。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值