LCT能干啥

 

 

 

模板:

 

  • 维护可加的树链信息:询问都是一条链上的信息;维护方式和线段树差不多;
  • 增加一条边;
  • 删除一条边;
  • 修改一个点权;
  • 修改一条路径上的所有点的点权;

 

 

整体来说,像是树链剖分的森林化,再用\(splay\)代替线段树;

 

 

\(eg.\) 染色

Tree II

 

 


 

 

维护MST

 

 

\(eg.\) 水管局长

 

 

题目要求删边,感觉删边比加边麻烦,我们可以用时光倒流法,将操作离线,沿时间轴从后往前倒着操作(撤回),会更加方便;

 

 

因为每往\(MST\)(最小生成树)中加入一条边,会产生一个环,需要在这个环上删除一条最大的边才能,重新得到\(MST\),这是\(LCT\)可以做到的;

 

 

我们遇到的的第一个问题是边权化点权,一个很方便的方法是,将每一条边都看成一个点,比如对于边\((x,y)\),它的编号是\(i\),每次连接时,都将\((x,i)\)和\((i,y)\)相连,这样构造出来的联通性是等价的;

边的权值被存储在\(i\)节点中,巧妙的解决了边权的问题;

 

 

对于维护\(MST\),可以记录这颗子树里最大的边权的编号,每次增加一条边,再将路径上最大的边删去即可;

 

 

 


 

 

维护双连通分量??

 

 

\(eg.\) 航线规划

感觉题目跟边双联通分量有关,将边双缩了点后,两点之间的边的数量就是我们要求的;

 

 

那删除一条边呢?

经验告诉我们,要时光倒流;

那加入一条边呢?

要重新缩点,那意思是······动态缩点???在\(LCT\)上缩点???

 

 

还是从题目本身入手吧;

先把边权化点权,用前面的方法,一个由边变来的点,才拥有权值,如果值为\(1\),意味着这条边是关键边,反之不是;

那\(LCT\)上就是维护一个子树和,询问查询路径和;

 

 

那加入一条边呢??(又来了)

比如加一条\((x,y)\),那\(x\)到\(y\)就会产生一个环,那\(x\)到\(y\)之间的边全都不再是关键边;那就可以打标记推平;

 

 

至此,这个题就是路径推平路径查询;

 

 

 


 

 

维护子树信息

 

 

链的情况我们能解决,那子树呢?

首先一定要明确,原树上的子树和\(LCT\)上的子树有巨大差别;

\(eg.\) 大融合

发现询问就是,在原树上删除\((x,y)\)得到的子树大小的乘积;

 

 

根据题目询问的特点,每次询问一条边\((x,y)\),我们可以把\(x,y\)这条链先单独取出来\(split(x,y)\);

这样我们所需要的信息就是\(x,y\)的虚子树大小的和;

 

 

怎么维护虚树子树信息(记为\(sz[x]\))???

我们发现虚树边只有在\(access\)和\(link\)函数时会发生改变;

 

 

\(access\)原函数

void access(int x)
{
for(int y=0;x;y=x,x=fa[x])
splay(x),rs=y,upd(x);
}

\(x\)的右儿子变了,我们应当在\(sz[x]\)减去\(y\)的贡献,而加上\(rs\)的贡献;

贡献是什么?这里应该指的是,实儿子和虚儿子总的子树大小和,毕竟\(x\)虚儿子所在的整个\(splay\)树都在\(x\)子树中;

这一部分应该为

void upd(int x){ s[x]=s[ls]+s[rs]+1+sz[x];}
void access(int x)
{
for(int y=0;x;x=fa[y=x])
{
splay(x),
sz[x]+=s[rs];
sz[x]-=s[y];
rs=y,upd(x);
}
}

 

 

而\(link\)呢?

原函数

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

这里就是连了一条虚边;

那应该把\(x\)的贡献加到\(y\)里;

但由于\(y\)的位置未知,就必须还把\(x\)的贡献加给\(y\)的父亲们;

 

 

为了解决这个问题,我们可以让\(y\)没有父亲;

具体来说把\(y\) \(splay\)到根的位置就可以了,即

void link(int x,int y)
{
makert(x);access(y);splay(y);
fa[x]=y;
sz[y]+=s[x];
upd(y);
}

 

 

这样就可以正确维护虚子树信息。

\(Code\)

#include<bits/stdc++.h>
#define ll long long
#define mp make_pair
using namespace std; const int N=200005;
int n,m; inline int read()
{
int x=0,fl=1;char st=getchar();
while(st<'0'||st>'9'){ if(st=='-')fl=-1; st=getchar();}
while(st>='0'&&st<='9') x=x*10+st-'0',st=getchar();
return x*fl;
} struct LCT
{
#define ls ch[x][0]
#define rs ch[x][1]
int fa[N],ch[N][2],tag[N],sz[N];
int v[N],s[N];
int sta[N];
bool nort(int x){ return ch[fa[x]][0]==x||ch[fa[x]][1]==x;}
void upd(int x){ s[x]=s[ls]+s[rs]+1+sz[x];}
void rev(int x){ swap(ls,rs);tag[x]^=1;}
void pd(int x)
{
if(tag[x])
{
if(ls) rev(ls);
if(rs) rev(rs);
tag[x]=0;
}
}
void rotate(int x)
{
int y=fa[x],ys=(ch[y][1]==x);
int R=fa[y];
int B=ch[x][ys^1];
if(nort(y)) ch[R][ch[R][1]==y]=x; ch[x][ys^1]=y; ch[y][ys]=B;
if(B) fa[B]=y; fa[x]=R; fa[y]=x;
upd(y);upd(x);
}
void splay(int x)
{
int y=x,z,top=0;
sta[++top]=y;
while(nort(y))
{
y=fa[y];
sta[++top]=y;
}
while(top) pd(sta[top--]);
while(nort(x))
{
y=fa[x];z=fa[y];
if(nort(y))
rotate((ch[y][1]==x)==(ch[z][1]==y)?y:x);
rotate(x);
}
}
void access(int x)
{
for(int y=0;x;x=fa[y=x])
{
splay(x),
sz[x]+=s[rs];
sz[x]-=s[y];
rs=y,upd(x);
}
}
void makert(int x)
{
access(x);splay(x);rev(x);
}
void split(int x,int y)
{
makert(x);access(y);splay(y);
}
void link(int x,int y)
{
makert(x);access(y);splay(y);
fa[x]=y;
sz[y]+=s[x];
upd(y);
}
}f; map<pair<int,int>,int> book;
char st[5]; int main()
{
n=read();m=read();
for(int i=1;i<=n;i++) f.s[i]=1;
for(int i=1;i<=m;i++)
{
scanf("%s",st);
int x=read(),y=read();
if(st[0]=='A')
{
f.link(x,y);
}
else
{
f.split(x,y);
printf("%lld\n",(ll)(f.sz[x]+1)*(f.sz[y]+1));
}
}
return 0;
}

 

 

 

 

\(to\ be\ continued\)

LCT能干啥???的更多相关文章

  1. 一堆LCT板子

    搞了一上午LCT,真是累死了-- 以前总觉得LCT高大上不好学不好打,今天打了几遍感觉还可以嘛= =反正现在的水平应付不太难的LCT题也够用了,就这样好了,接下来专心搞网络流. 话说以前一直YY不出来 ...

  2. 动态树之LCT(link-cut tree)讲解

    动态树是一类要求维护森林的连通性的题的总称,这类问题要求维护某个点到根的某些数据,支持树的切分,合并,以及对子树的某些操作.其中解决这一问题的某些简化版(不包括对子树的操作)的基础数据结构就是LCT( ...

  3. 在此为LCT开一个永久的坑

    其实我连splay都还不怎么会. 今天先抄了黄学长的bzoj2049,以后一定要把它理解了. 写LCT怎么能不%数据结构大神yeweining呢?%%%chrysanthemums  %%%切掉大森林 ...

  4. 【BZOJ2157】旅游 LCT

    模板T,SB的DMoon..其实样例也是中国好样例...一开始不会复制,yangyang:找到“sample input”按住shift,按page down.... #include <ios ...

  5. 【BZOJ3669】[Noi2014]魔法森林 LCT

    终于不是裸的LCT了...然而一开始一眼看上去这是kruskal..不对,题目要求1->n的路径上的每个点的两个最大权值和最小,这样便可以用LCT来维护一个最小生成路(瞎编的...),先以a为关 ...

  6. 【BZOJ1180】: [CROATIAN2009]OTOCI & 2843: 极地旅行社 LCT

    竟然卡了我....忘记在push_down先下传父亲的信息了....还有splay里for():卡了我10min,但是双倍经验还是挺爽的,什么都不用改. 感觉做的全是模板题,太水啦,不能这么水了... ...

  7. 【BZOJ3282】Tree LCT

    1A爽,感觉又对指针重怀信心了呢= =,模板题,注意单点修改时splay就好,其实按吾本意是没写的也A了,不过应该加上能更好维护平衡性. ..还是得加上好= = #include <iostre ...

  8. BZOJ2888 资源运输(LCT启发式合并)

    这道题目太神啦! 我们考虑他的每一次合并操作,为了维护两棵树合并后树的重心,我们只好一个一个的把节点加进去.那么这样一来看上去似乎就是一次操作O(nlogn),但是我们拥有数据结构的合并利器--启发式 ...

  9. LCT裸题泛做

    ①洞穴勘测 bzoj2049 题意:由若干个操作,每次加入/删除两点间的一条边,询问某两点是否连通.保证任意时刻图都是一个森林.(两点之间至多只有一条路径) 这就是个link+cut+find roo ...

随机推荐

  1. Previous operation has not finished; run 'cleanup' if it was interrupted最简单有效的解决方法

    今天提交代码报错,看了看提示的错误,百度了一下,发现操作都比较繁琐,所以自己重新给一个最简单有效的. 有的要下载sqlite3.exe,借助它清空本地.svn\wc.db数据库文件里面的operati ...

  2. Java虚拟机详解(九)------类文件结构

    我们知道计算机是由晶体管.电路板等组装而成的电子设备,而这些电子设备其实只能识别0与1的信号. 那么问题来了,我们在操作系统上编写的Java代码(由字母.数字等各种符号组成),打包后部署到服务器上,是 ...

  3. Java——内部类详解

    说起内部类,大家肯定感觉熟悉又陌生,因为一定在很多框架源码中有看到别人使用过,但又感觉自己使用的比较少,今天我就带你具体来看看内部类. 内部类基础 所谓内部类就是在类的内部继续定义其他内部结构类. 在 ...

  4. Gemini.Workflow 双子工作流高级教程:数据库设计及各表作用说明

    整体数据库设计,可见这一篇:Gemini.Workflow 双子工作流高级教程:数据库-设计文档 这里对各数据表进行介绍: 工作流里的设计表并不多,核心只有以下8个: 下面按照流程的顺序来介绍一下表的 ...

  5. 【Luogu P3384】树链剖分模板

    树链剖分的基本思想是把一棵树剖分成若干条链,再利用线段树等数据结构维护相关数据,可以非常暴力优雅地解决很多问题. 树链剖分中的几个基本概念: 重儿子:对于当前节点的所有儿子中,子树大小最大的一个儿子就 ...

  6. tensorflow的函数

    1. if __name__=="__main__": tf.app.run()#运行之前定义的main函数#将传进来的参数,以及flags.FLAGS定义的参数传入到main函数 ...

  7. .Net Core使用分布式缓存Redis:基础

    一.前言 Redis的介绍网上很多不再赘述.本次环境为net core 2.2,使用的StackExchange.Redis来操作Redis. 二.引用Microsoft.Extensions.Cac ...

  8. mybatis的@Options的使用

    1.问题: 我采用的是mybatis的注解方式,打算插入一条数据之后返回主键,但是试了好几次都是返回的影响的记录数:1, @Insert(****) @Options(useGeneratedKeys ...

  9. python文件高级操作

    python文件高级操作和注意事项等等 文件过大保护 由于read是一次性读取文件所有的内容,如果文件100G,内存就会吃不消,所以推荐使用read(size)一次读取指定字节/字符(根据rb,或者r ...

  10. Linux网络相关、firewalld和netfilter、netfilter5表5链介绍、iptables语法 使用介绍

    第7周第3次课(5月9日) 课程内容: 10.11 Linux网络相关10.12 firewalld和netfilter10.13 netfilter5表5链介绍10.14 iptables语法 扩展 ...