LCT(Link-Cut Tree)
Link-cut tree(LCT)【可以理解为树链剖分+splay】
给出如下定义:
access(x):访问x节点
perferred child:若以x为根的子树中最后被访问的节点在以x的儿子y为根的子树中,则称y为节点x的preferred child
preferred edge:节点x与其preferred child之间的边
preferred path:由preferred edge组成的路径
每条preferred path用splay维护,记录splay的根接到上条重链的哪个节点
操作
每次访问一个点时,该点一直到根的路径上的点全部被修改,与preferred child断开并连到新的preferred child上,并打上翻转标记,也就是拆分(cut)和合并(link)两个操作,其余链上的维护可以通过下传标记(pushdown)解决
例题:
bzoj2002弹飞绵羊
#include<iostream>
#include<algorithm>
#include<cstdio>
#include<cstring>
using namespace std;
const int Mx=;
int n,m,fa[Mx],l[Mx],r[Mx],root[Mx],siz[Mx],rev[Mx];
void pushup(int x) { siz[x]=siz[l[x]]+siz[r[x]]+; }
void pushdown(int x) { if(rev[x]) rev[x]^=,rev[l[x]]^=,rev[r[x]]^=,swap(l[x],r[x]); }
void rotate(int x)
{
int y=fa[x];
if(l[y]==x) l[y]=r[x],fa[r[x]]=y,r[x]=y,fa[x]=fa[y],fa[y]=x;
else r[y]=l[x],fa[l[x]]=y,l[x]=y,fa[x]=fa[y],fa[y]=x;
if(root[y]) root[y]=,root[x]=;
else
if(r[fa[x]]==y) r[fa[x]]=x;
else l[fa[x]]=x;
pushup(y);
}
void splay(int x)
{
while(!root[x])
{
int y=fa[x],yy=fa[y];
if(root[y]) rotate(x);
else
if((l[yy]==y&&l[y]!=x)||(l[yy]!=y&&l[y]==x)) rotate(y),rotate(x);
else rotate(x),rotate(x);
}
pushup(x);
}
void access(int x)
{
int y=;
while(x)
{
splay(x); root[r[x]]=,root[y]=;
pushup(x); r[x]=y,y=x,x=fa[x];
}
}
void rever(int x) { access(x); splay(x); rev[x]^=; }
void link(int x,int y) { rever(x); fa[l[x]]=,root[l[x]]=,l[x]=,fa[x]=y; pushup(x); }
void cut(int x,int y) { rever(x); access(y); splay(y); l[y]=,fa[x]=; }
int main()
{
scanf("%d",&n);
for(int i=;i<=n;i++) root[i]=,siz[i]=;
for(int i=;i<=n;i++)
{
int x; scanf("%d",&x);
if(i+x<=n) link(i,i+x);
}
scanf("%d",&m);
while(m--)
{
int num,x,k; scanf("%d",&num);
if(num==)
{
scanf("%d",&x); x++;
rever(x);
printf("%d\n",siz[l[x]]+);
}
else
{
scanf("%d%d",&x,&k); x++;
if(x+k>n) link(x,);
else link(x,x+k);
}
}
}
bzoj2631 tree
#include<iostream>
#include<algorithm>
#include<cstdio>
#include<cstring>
using namespace std;
const int Mx=;
const int p=;
int n,top,q[Mx],fa[Mx],son[Mx][],siz[Mx],rev[Mx];
unsigned int val[Mx],sum[Mx],add_tag[Mx],mul_tag[Mx];
inline int read()
{
int x=,f=;char ch=getchar();
while(ch<''||ch>''){if(ch=='-')f=-;ch=getchar();}
while(ch>=''&&ch<=''){x=x*+ch-'';ch=getchar();}
return x*f;
}
void cal(int x,int a,int b)
{
if(!x) return ;
val[x]=(a*val[x]+b)%p;
sum[x]=(a*sum[x]+b*siz[x])%p;
add_tag[x]=(a*add_tag[x]+b)%p;
mul_tag[x]=(a*mul_tag[x])%p;
}
int isroot(int x)
{
if(son[fa[x]][]!=x&&son[fa[x]][]!=x) return ;
return ;
}
void pushup(int x)
{
int l=son[x][],r=son[x][];
sum[x]=(sum[l]+sum[r]+val[x])%p;
siz[x]=(siz[l]+siz[r]+)%p;
}
void pushdown(int x)
{
int l=son[x][],r=son[x][];
if(rev[x])
rev[x]^=,rev[l]^=,rev[r]^=,
swap(son[x][],son[x][]);
int a=add_tag[x],m=mul_tag[x];
add_tag[x]=,mul_tag[x]=;
if(a!=||m!=) cal(l,m,a),cal(r,m,a);
}
void rotate(int x)
{
int l=,r=,y=fa[x],yy=fa[y];
if(son[y][]==x) l=; r=l^;
if(!isroot(y)) son[yy][(son[yy][]==y)]=x;
fa[x]=yy,fa[y]=x,fa[son[x][r]]=y,son[y][l]=son[x][r],son[x][r]=y;
pushup(y);pushup(x);
}
void splay(int x)
{
q[++top]=x;
for(int i=x;!isroot(i);i=fa[i]) q[++top]=fa[i];
while(top) pushdown(q[top--]);
while(!isroot(x))
{
int y=fa[x],yy=fa[y];
if(!isroot(y))
{
if((son[y][]==x)^(son[yy][]==y)) rotate(x);
else rotate(y);
}
rotate(x);
}
}
void access(int x)
{
for(int t=;x;t=x,x=fa[x])
splay(x),son[x][]=t,pushup(x);
}
void rever(int x)
{
access(x); splay(x); rev[x]^=;
}
void link(int x,int y)
{
rever(x); fa[x]=y;
}
void split(int x,int y)
{
rever(y); access(x); splay(x);
}
void cut(int x,int y)
{
rever(x); access(y); splay(y);
son[y][]=fa[x]=;
}
signed main()
{
int m; scanf("%d%d",&n,&m);
for(int i=;i<=n;i++) val[i]=sum[i]=mul_tag[i]=siz[i]=;
for(int i=,x,y;i<n;i++) scanf("%d%d",&x,&y),link(x,y);
while(m--)
{
char ch[]; scanf("%s",ch); int x,y,c; x=read(),y=read();
if(ch[]=='+') c=read(),split(x,y),cal(x,,c);
if(ch[]=='-') cut(x,y),x=read(),y=read(),link(x,y);
if(ch[]=='*') c=read(),split(x,y),cal(x,c,);
if(ch[]=='/') split(x,y),printf("%d\n",sum[x]);
}
return ;
}
LCT(Link-Cut Tree)的更多相关文章
- LCT(Link Cut Tree)总结
概念.性质简述 首先介绍一下链剖分的概念链剖分,是指一类对树的边进行轻重划分的操作,这样做的目的是为了减少某些链上的修改.查询等操作的复杂度.目前总共有三类:重链剖分,实链剖分和并不常见的长链剖分. ...
- FOJ题目Problem 2082 过路费 (link cut tree边权更新)
Problem 2082 过路费 Accept: 382 Submit: 1279 Time Limit: 1000 mSec Memory Limit : 32768 KB Proble ...
- bzoj 3282: Tree (Link Cut Tree)
链接:https://www.lydsy.com/JudgeOnline/problem.php?id=3282 题面: 3282: Tree Time Limit: 30 Sec Memory L ...
- HDOJ 题目2475 Box(link cut tree去点找祖先)
Box Time Limit: 10000/5000 MS (Java/Others) Memory Limit: 32768/32768 K (Java/Others) Total Submi ...
- POJ 题目3237 Tree(Link Cut Tree边权变相反数,求两点最大值)
Tree Time Limit: 5000MS Memory Limit: 131072K Total Submissions: 6131 Accepted: 1682 Description ...
- BZOJ 题目1036: [ZJOI2008]树的统计Count(Link Cut Tree,改动点权求两个最大值和最大值)
1036: [ZJOI2008]树的统计Count Time Limit: 10 Sec Memory Limit: 162 MB Submit: 8421 Solved: 3439 [Submi ...
- URAL 题目1553. Caves and Tunnels(Link Cut Tree 改动点权,求两点之间最大)
1553. Caves and Tunnels Time limit: 3.0 second Memory limit: 64 MB After landing on Mars surface, sc ...
- LCT总结——概念篇+洛谷P3690[模板]Link Cut Tree(动态树)(LCT,Splay)
为了优化体验(其实是强迫症),蒟蒻把总结拆成了两篇,方便不同学习阶段的Dalao们切换. LCT总结--应用篇戳这里 概念.性质简述 首先介绍一下链剖分的概念(感谢laofu的讲课) 链剖分,是指一类 ...
- LuoguP3690 【模板】Link Cut Tree (动态树) LCT模板
P3690 [模板]Link Cut Tree (动态树) 题目背景 动态树 题目描述 给定n个点以及每个点的权值,要你处理接下来的m个操作.操作有4种.操作从0到3编号.点从1到n编号. 0:后接两 ...
- P3690 【模板】Link Cut Tree (动态树)
P3690 [模板]Link Cut Tree (动态树) 认父不认子的lct 注意:不 要 把 $fa[x]$和$nrt(x)$ 混 在 一 起 ! #include<cstdio> v ...
随机推荐
- 基于 Ubuntu + nextCloud 搭建自己的私人网盘
提醒一下,如果之前通过apache搭建了网站,不要用snap命令来搭建,否则,至少有一个无法正常运行(不要问我怎么知道的,都是血的教训啊). 你可以通过腾讯云的实验主机进行尝试. 1.基础设置 切换为 ...
- 2018.4.16 Java多线程实现龟兔赛跑
龟兔赛跑(通过多线程来实现 里面的具体方法) TT.java package com.lanqiao.demo3; /** * 乌龟 * @author Administrator * */ publ ...
- stixel-world和psmnet结合出现的问题
float32位,4字节 原本的stixel-world是用sgbm生成深度图,并且转成了float型 psmnet保存最终的disparity图是保存成uint16的,skimage.io.imsa ...
- pysql用类进行封装
pyMySQL用类进行封装 class SqlHelper(object): def __init__(self): self.connect() def connect(self): self.co ...
- JTT808、JTT809、JTT796、JTT794、JTT1077、JTT1078区别与交通部道路运输车辆卫星定位系统部标标准大全下载地址
部标JT/T808协议.JT/T809协议.JT/T796标准.JT/T794标准的区别,他们是基于不同的通信场景,不同的通信对象,不同的设计目的和目标而制定出来的.首先要知道这些标准的全称是什么意思 ...
- iOS开发-动画总结
一.简介 IOS 动画主要是指Core Animation框架.官方使用文档地址为:Core Animation Guide.Core Animation是IOS和OS X平台上负责图形渲染与动画的基 ...
- 解决Windows 与Mac 双系统下的蓝牙设备共用的问题
不知道有多少人和我一样用的蓝牙鼠标或者键盘,有的话应该都会遇到同一个问题:即在一个系统下配好对后在另一个系统必须重新配对才能使用,很是麻烦.还要将蓝牙设备进入发现模式,OS下搜索,连接....终于昨天 ...
- 理解JWT的使用场景和优劣
理解JWT的使用场景和优劣 淘楼小能手 百家号04-2816:20 经过前面两篇文章<JSON Web Token - 在Web应用间安全地传递信息><八幅漫画理解使用JSON We ...
- php 常用函数集合(持续更新中...)
php 常用函数集合 在php的开发中,巧妙的运用php自带的一些函数,会起到事半功倍的效果,在此,主要记录一些常用的函数 1.time(),microtime()函数 time():获取当前时间戳 ...
- Python头脑风暴2
今天想到了一个致富新途径:假如我在X东上班,我写个X宝爬虫,专门爬在X宝买奢侈品的土豪,然后我自己注册个X宝号,用脚本一个个加他们然后给他们发信息说我X东这还有比你更便宜更好的...不知道行不行啊(狗 ...