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 ...
随机推荐
- bower使用
1,先安装nodejs(npm),Git 2,安装bower cmd执行到在项目文件夹下路径,执行npm install bower 3,执行bower init 项目根目录下将生成bower.js ...
- 解决AjaxFileUpload中文化/国际化的问题。
由微软官方提供的AjaxControlToolKit,在ASP.NET开发过程中,确实能够给开发者带来很多的便利,节约开发者的重复劳动.这套控件也是比较成熟的,在性能方面也不会太差,至少能够满足一般开 ...
- 几种排序算法的比较转自http://blog.csdn.net/keenweiwei/article/details/3697452
1冒泡排序: 已知一组无需数据a[1],a[2],a[3],a[4],a[5][a[n],将其按升序排列,首先找出这组数据中最大值,将a[1]与a[2]比较,若a[1]大,则交换两者的值,否则不变,在 ...
- redis学习笔记(2)
redis学习笔记第二部分 --配置文件介绍 二,解析redis的配置文件redis.conf常见配置参数说明redis.conf 配置项说明如下:1. Redis默认不是以守护进程的方式运行,可以通 ...
- IE浏览器缓存问题解决方法(非常严重)
IE浏览器缓存问题解决方法整理 一.IE浏览器缓存的内容分析: IE浏览器会缓存网页中的GET和XHR的内容,并且在IE浏览器中如果请求方式是get方式的话,IE浏览器会进行识别,如果该get请求的u ...
- 谷歌放弃“不作恶” Alphabet要“遵守法律互相尊重”
对于一些谷歌粉而言,谷歌那条“不作恶(Don’t be evil)”的行为准则是他们引以为傲的精神信仰.这一准则于1999年被首次确认,谷歌在2004年申请上市时也提到了这一点.不过现在这一点要改变了 ...
- NO_PUBKEY
* 现象:$ sudo apt-get update时警告如下: W: GPG error: http://ppa.launchpad.net precise Release: The followi ...
- /dev/sda is apparently in use by the system; will not make a filesystem here!解决方法
/dev/sda is apparently in use by the system; will not make a filesystem here! 翻译:系统显然在使用,不会在这里做文件系统 ...
- PHP GD库---之头像合成九宫格
public function createMosaicGroupAvatar($pic_list = array(), $bg_w = 396, $bg_h = 396) { if (!$pic_l ...
- ReportViewer部分使用总结
最近winform上使用ReportViewer做报表,因为之前没弄过,所以遇到了很多问题,现在总结一下. 一.运行环境 .net环境:4.0 开发工具:vs2010 二.开发步骤 第一步,在winf ...