这应该暂时是个终结篇了...

最后在这里讨论LCT的一个常用操作:维护虚子树信息

这也是一个常用操作

下面我们看一下如何来维护

以下内容转自https://blog.csdn.net/neither_nor/article/details/52979425

对于一个点x,如果我们对x进行access操作,那么他的虚子树内将包含且仅包含他原树中子树内除了他自己以外的所有点,这时如果我们维护了他的虚子树信息和,我们把这个信息与他自己的信息合并,我们就得到了他在原树中的子树信息

在下面的讨论中,我们发现我们可以同时维护一个点的虚子树信息和LCT子树信息来达到维护虚子树信息的目的

考虑一个点的虚子树信息会在什么情况下发生改变,一个点的虚子树信息改变,当且仅当进行link或者access操作时。

在进行access操作时,我们会有更换一个点的x右儿子的操作,这时我们要把x原来的右儿子的LCT子树信息加入x的虚子树信息,把x的新的右儿子的LCT子树信息从x的虚子树信息中减去

在进行link操作时,我们会先把点x换根,然后连一条x到y的虚边,这时我们发现不仅y的虚子树信息需要加入x的LCT子树信息,y的所有祖先的LCT子树信息也需要更改,而这样我们就没法维护了,所以在进行link操作的时候我们需要把y也换根(其实access再splay就行了,不用换成根),这样就只会对y的虚子树信息和LCT子树信息产生影响

我们还需要维护一个x的LCT子树的信息和,x的LCT子树的信息和就等于x的实儿子的LCT子树信息和加上x的虚子树的信息和加上x自己,在splay的update函数中就可以直接维护

这样我们就完成了对子树信息的维护

换根操作、cut操作和链修改操作并不影响我们上边的讨论,所以也是兹磁的

转载结束

例:bzoj 4530大融合

#include <cstdio>
#include <cmath>
#include <cstring>
#include <cstdlib>
#include <iostream>
#include <algorithm>
#include <queue>
#include <stack>
using namespace std;
int c[100005][2];
int f[100005];
bool ttag[100005];
int si[100005];
int s[100005];
void update(int rt)
{
s[rt]=s[c[rt][0]]+s[c[rt][1]]+si[rt]+1;
}
bool berot(int rt)
{
if(c[f[rt]][0]==rt||c[f[rt]][1]==rt)
{
return 0;
}
return 1;
}
void reverse(int rt)
{
swap(c[rt][0],c[rt][1]);
ttag[rt]^=1;
}
void pushdown(int rt)
{
if(ttag[rt])
{
if(c[rt][0])
{
reverse(c[rt][0]);
}
if(c[rt][1])
{
reverse(c[rt][1]);
}
ttag[rt]=0;
}
}
void repush(int rt)
{
if(!berot(rt))
{
repush(f[rt]);
}
pushdown(rt);
}
void rotate(int rt)
{
int ltyp=0;
int fa=f[rt];
int ffa=f[fa];
if(c[fa][1]==rt)
{
ltyp=1;
}
if(!berot(fa))
{
if(c[ffa][0]==fa)
{
c[ffa][0]=rt;
}else
{
c[ffa][1]=rt;
}
}
c[fa][ltyp]=c[rt][ltyp^1];
c[rt][ltyp^1]=fa;
f[c[fa][ltyp]]=fa;
f[fa]=rt;
f[rt]=ffa;
update(fa);
}
void splay(int rt)
{
repush(rt);
while(!berot(rt))
{
int fa=f[rt];
int ffa=f[fa];
int jr=f[ffa];
if(!berot(fa))
{
if((c[fa][0]==rt&&c[ffa][0]!=fa)||(c[fa][1]==rt&&c[ffa][1]!=fa))
{
rotate(rt);
}else
{
rotate(fa);
}
}
rotate(rt);
}
update(rt);
}
void access(int rt)
{
int y=0;
while(rt)
{
splay(rt);
si[rt]+=s[c[rt][1]];
c[rt][1]=y;
si[rt]-=s[c[rt][1]];
update(rt);
y=rt;
rt=f[rt];
}
}
void makeroot(int rt)
{
access(rt);
splay(rt);
reverse(rt);
}
void split(int st,int ed)
{
makeroot(st);
access(ed);
splay(ed);
}
void link(int st,int ed)
{
split(st,ed);
f[st]=ed;
si[ed]+=s[st];
update(ed);
} inline int read()
{
int f=1,x=0;char ch=getchar();
while(ch<'0'||ch>'9'){if(ch=='-')f=-1;ch=getchar();}
while(ch>='0'&&ch<='9'){x=x*10+ch-'0';ch=getchar();}
return x*f;
}
int n,q;
char ss[5];
int main()
{
scanf("%d%d",&n,&q);
for(int i=1;i<=n;i++)
{
s[i]=1;
}
while(q--)
{
scanf("%s",ss);
int x=read(),y=read();
if(ss[0]=='A')
{
link(x,y);
}else
{
split(x,y);
printf("%lld\n",(long long)(si[x]+1)*(long long)(si[y]+1));
}
}
return 0;
}

例:bzoj 3510首都

#include <cstdio>
#include <cmath>
#include <cstring>
#include <cstdlib>
#include <iostream>
#include <algorithm>
#include <queue>
#include <stack>
using namespace std;
int c[100005][2];
int f[100005];
int ff[100005];
int s[100005];
int si[100005];
bool ttag[100005];
int tot=0;
int findf(int x)
{
if(x==ff[x])
{
return x;
}
return ff[x]=findf(ff[x]);
}
void update(int rt)
{
s[rt]=s[c[rt][0]]+s[c[rt][1]]+si[rt]+1;
}
bool berot(int rt)
{
if(c[f[rt]][0]==rt||c[f[rt]][1]==rt)
{
return 0;
}
return 1;
}
void reverse(int rt)
{
swap(c[rt][0],c[rt][1]);
ttag[rt]^=1;
}
void pushdown(int rt)
{
if(ttag[rt])
{
reverse(c[rt][0]);
reverse(c[rt][1]);
ttag[rt]=0;
}
}
void repush(int rt)
{
if(!berot(rt))
{
repush(f[rt]);
}
pushdown(rt);
}
void rotate(int rt)
{
int ltyp=0;
int fa=f[rt];
int ffa=f[fa];
if(c[fa][1]==rt)
{
ltyp=1;
}
if(!berot(fa))
{
if(c[ffa][1]==fa)
{
c[ffa][1]=rt;
}else
{
c[ffa][0]=rt;
}
}
c[fa][ltyp]=c[rt][ltyp^1];
c[rt][ltyp^1]=fa;
f[c[fa][ltyp]]=fa;
f[fa]=rt;
f[rt]=ffa;
update(fa);
}
void splay(int rt)
{
repush(rt);
while(!berot(rt))
{
int fa=f[rt];
int ffa=f[fa];
if(!berot(fa))
{
if((c[fa][0]==rt&&c[ffa][0]!=fa)||(c[fa][1]==rt&&c[ffa][1]!=fa))
{
rotate(rt);
}else
{
rotate(fa);
}
}
rotate(rt);
}
update(rt);
}
void access(int rt)
{
int y=0;
while(rt)
{
splay(rt);
si[rt]+=s[c[rt][1]];
c[rt][1]=y;
si[rt]-=s[c[rt][1]];
update(rt);
y=rt;
rt=f[rt];
}
}
void makeroot(int rt)
{
access(rt);
splay(rt);
reverse(rt);
}
void split(int st,int ed)
{
makeroot(st);
access(ed);
splay(ed);
}
void link(int st,int ed)
{
split(st,ed);
f[st]=ed;
si[ed]+=s[st];
update(ed);
}
int query(int rt)
{
int ls=0,rs=0,ltemp=0,rtemp=0;
int ed=s[rt]>>1;
bool flag=s[rt]%2;
int ret=0x3f3f3f3f;
while(rt)
{
pushdown(rt);
int lc=c[rt][0];
int rc=c[rt][1];
ltemp=ls+s[lc];
rtemp=rs+s[rc];
if(ltemp<=ed&&rtemp<=ed)
{
if(flag)
{
ret=rt;
break;
}else if(rt<ret)
{
ret=rt;
}
}
if(ltemp<rtemp)
{
ls+=s[lc]+si[rt]+1;
rt=rc;
}else
{
rs+=s[rc]+si[rt]+1;
rt=lc;
}
}
splay(ret);
return ret;
}
inline int read()
{
int f=1,x=0;char ch=getchar();
while(ch<'0'||ch>'9'){if(ch=='-')f=-1;ch=getchar();}
while(ch>='0'&&ch<='9'){x=x*10+ch-'0';ch=getchar();}
return x*f;
}
int n,m;
char ss[10];
int main()
{
n=read(),m=read();
for(int i=1;i<=n;i++)
{
tot^=i;
s[i]=1;
ff[i]=i;
}
while(m--)
{
scanf("%s",ss);
if(ss[0]=='A')
{
int x=read(),y=read();
link(x,y);
int f1=findf(x);
int f2=findf(y);
split(f1,f2);
int rf=query(f2);
tot=tot^f1^f2^rf;
ff[f1]=ff[f2]=ff[rf]=rf;
}else if(ss[0]=='Q')
{
int x=read();
printf("%d\n",findf(x));
}else
{
printf("%d\n",tot);
}
}
return 0;
}

SPLAY,LCT学习笔记(六)的更多相关文章

  1. LCT 学习笔记

    LCT学习笔记 前言 自己定的学习计划看起来完不成了(两天没学东西,全在补题),决定赶快学点东西 于是就学LCT了 简介 Link/Cut Tree是一种数据结构,我们用它解决动态树问题 但是LCT不 ...

  2. java之jvm学习笔记六-十二(实践写自己的安全管理器)(jar包的代码认证和签名) (实践对jar包的代码签名) (策略文件)(策略和保护域) (访问控制器) (访问控制器的栈校验机制) (jvm基本结构)

    java之jvm学习笔记六(实践写自己的安全管理器) 安全管理器SecurityManager里设计的内容实在是非常的庞大,它的核心方法就是checkPerssiom这个方法里又调用 AccessCo ...

  3. Learning ROS for Robotics Programming Second Edition学习笔记(六) indigo xtion pro live

    中文译著已经出版,详情请参考:http://blog.csdn.net/ZhangRelay/article/category/6506865 Learning ROS for Robotics Pr ...

  4. Typescript 学习笔记六:接口

    中文网:https://www.tslang.cn/ 官网:http://www.typescriptlang.org/ 目录: Typescript 学习笔记一:介绍.安装.编译 Typescrip ...

  5. python3.4学习笔记(六) 常用快捷键使用技巧,持续更新

    python3.4学习笔记(六) 常用快捷键使用技巧,持续更新 安装IDLE后鼠标右键点击*.py 文件,可以看到Edit with IDLE 选择这个可以直接打开编辑器.IDLE默认不能显示行号,使 ...

  6. Go语言学习笔记六: 循环语句

    Go语言学习笔记六: 循环语句 今天学了一个格式化代码的命令:gofmt -w chapter6.go for循环 for循环有3种形式: for init; condition; increment ...

  7. 【opencv学习笔记六】图像的ROI区域选择与复制

    图像的数据量还是比较大的,对整张图片进行处理会影响我们的处理效率,因此常常只对图像中我们需要的部分进行处理,也就是感兴趣区域ROI.今天我们来看一下如何设置图像的感兴趣区域ROI.以及对ROI区域图像 ...

  8. Linux学习笔记(六) 进程管理

    1.进程基础 当输入一个命令时,shell 会同时启动一个进程,这种任务与进程分离的方式是 Linux 系统上重要的概念 每个执行的任务都称为进程,在每个进程启动时,系统都会给它指定一个唯一的 ID, ...

  9. # go微服务框架kratos学习笔记六(kratos 服务发现 discovery)

    目录 go微服务框架kratos学习笔记六(kratos 服务发现 discovery) http api register 服务注册 fetch 获取实例 fetchs 批量获取实例 polls 批 ...

  10. Spring Boot 学习笔记(六) 整合 RESTful 参数传递

    Spring Boot 学习笔记 源码地址 Spring Boot 学习笔记(一) hello world Spring Boot 学习笔记(二) 整合 log4j2 Spring Boot 学习笔记 ...

随机推荐

  1. Python基础【day01】:初始模块(五)

    本节内容 1.标准库 1.sys 2.os 2.第三方库 1.for mac 2.for linux Python的强大之处在于他有非常丰富和强大的标准库和第三方库,几乎你想实现的任何功能都有相应的P ...

  2. 震惊!最全PyCharm教程

    PyCharm PyCharm是一个用于计算机编程的集成开发环境(IDE),主要用于Python语言开发,由捷克公司JetBrains开发,提供代码分析.图形化调试器,集成测试器.集成版本控制系统(V ...

  3. Linux安装mysql过程(转+完善)

    http://blog.csdn.net/jerome_s/article/details/52883234yum 安装MySQL   1. 检查安装情况           查看有没有安装过:   ...

  4. Selenium自动化Page模式(Python)

    Selenium是当前主流的web自动化工具,提供了多种浏览器的支持(Chrome,Firefox, IE等等),当然大家也可以用自己喜欢的语言(Java,C#,Python等)来写用例,很容易上手. ...

  5. 第三次实验计算分段函数 第四次计算分段函数和循环NEW 第五次分支+循环加强版 实验报告

    一.实验题目,设计思路,实现方法 第四次分支+循环 加强版 (2-2计算个人所得税,2-7 装睡,2-8计算天数) 设计思路:2-2 用if-else的语句,与计算分段函数的题类似的做法:2-7 运用 ...

  6. 第三周结对项目--小学生四则运算CAI软件汇报及总结(UI/web)

    前言: 这周是和我队友苏卫喜一起结对开发,我主要是写项目文档需求分析,她是通过我的需求文档来进行做思维导图,之后我们通过思维导图一起讨论用户界面设计. 以下就是我的需求分析1.0版本 1.   软件名 ...

  7. Git操作学习笔记

    根据廖雪峰老师git教程学习整理 这里需要辨析一下概念.Github是代码托管平台,是协作的工具;而Git是版本控制工具.Git不需要联网,在本机就可以使用 集中式版本控制系统与分布式版本控制系统 S ...

  8. undefined reference问题总结

    http://ticktick.blog.51cto.com/823160/431329 http://blog.sina.com.cn/s/blog_605f5b4f01018xeu.html ht ...

  9. 2018-2019-2 网络对抗技术 20165320 Exp2 后门原理与实践

    后门原理与实践 windows获取Linux操作Shell 获取本机的IP netcat介绍:一个进行基本的TCP.UDP数据收发的工具 相关的参数与具体用法 windows打开监听: ncat.ex ...

  10. Python写黑客小工具,360免杀

    构思: client:反向连接server,执行shell命令 server:发送命令,控制客户端 import subprocess import socket import threading t ...