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)的更多相关文章

  1. LCT(Link Cut Tree)总结

    概念.性质简述 首先介绍一下链剖分的概念链剖分,是指一类对树的边进行轻重划分的操作,这样做的目的是为了减少某些链上的修改.查询等操作的复杂度.目前总共有三类:重链剖分,实链剖分和并不常见的长链剖分. ...

  2. FOJ题目Problem 2082 过路费 (link cut tree边权更新)

    Problem 2082 过路费 Accept: 382    Submit: 1279 Time Limit: 1000 mSec    Memory Limit : 32768 KB Proble ...

  3. bzoj 3282: Tree (Link Cut Tree)

    链接:https://www.lydsy.com/JudgeOnline/problem.php?id=3282 题面: 3282: Tree Time Limit: 30 Sec  Memory L ...

  4. HDOJ 题目2475 Box(link cut tree去点找祖先)

    Box Time Limit: 10000/5000 MS (Java/Others)    Memory Limit: 32768/32768 K (Java/Others) Total Submi ...

  5. POJ 题目3237 Tree(Link Cut Tree边权变相反数,求两点最大值)

    Tree Time Limit: 5000MS   Memory Limit: 131072K Total Submissions: 6131   Accepted: 1682 Description ...

  6. BZOJ 题目1036: [ZJOI2008]树的统计Count(Link Cut Tree,改动点权求两个最大值和最大值)

    1036: [ZJOI2008]树的统计Count Time Limit: 10 Sec  Memory Limit: 162 MB Submit: 8421  Solved: 3439 [Submi ...

  7. 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 ...

  8. LCT总结——概念篇+洛谷P3690[模板]Link Cut Tree(动态树)(LCT,Splay)

    为了优化体验(其实是强迫症),蒟蒻把总结拆成了两篇,方便不同学习阶段的Dalao们切换. LCT总结--应用篇戳这里 概念.性质简述 首先介绍一下链剖分的概念(感谢laofu的讲课) 链剖分,是指一类 ...

  9. LuoguP3690 【模板】Link Cut Tree (动态树) LCT模板

    P3690 [模板]Link Cut Tree (动态树) 题目背景 动态树 题目描述 给定n个点以及每个点的权值,要你处理接下来的m个操作.操作有4种.操作从0到3编号.点从1到n编号. 0:后接两 ...

  10. P3690 【模板】Link Cut Tree (动态树)

    P3690 [模板]Link Cut Tree (动态树) 认父不认子的lct 注意:不 要 把 $fa[x]$和$nrt(x)$ 混 在 一 起 ! #include<cstdio> v ...

随机推荐

  1. [学习笔记] C++ 历年试题解析(一)--判断题

    少说话.. 程序题链接:https://www.cnblogs.com/aoru45/p/9898691.html 14级试题---选择题 1. 引用在声明时必须对其初始化,以绑定某个已经存在的变量( ...

  2. 2018.2.10 使用SSH连接远程滴滴云服务器Ubuntu (Windows下) 及 putty工具永久设置字体、颜色

    一开始会有人问云服务器是什么? 云服务器是一种类似VPS服务器的虚拟化技术, VPS是采用虚拟软件,VZ或VM在一台服务器上虚拟出多个类似独立服务器的部分,每个部分都可以做单独的操作系统,管理方法同服 ...

  3. Python -- 可迭代对象和迭代器

    5.9 可迭代对象 可迭代对象: str , list , tuple , set , dict , range 1.在Python中,但凡内部有__iter__方法的对象,都是可迭代对象 2.查看对 ...

  4. 酷炫的3D照片墙

    今天给大家分享的案例是酷炫的3D照片墙 这个案例主要是通过 CSS3 和原生的 JS 来实现的,接下来我给大家分享一下这个效果实现的过程.博客上不知道怎么放本地视频,所以只能放两张效果截图了. 1.实 ...

  5. PCA检测人脸的简单示例_matlab实现

    PCA检测人脸的简单示例,matlab R2009b上实现训练:训练用的20副人脸: %训练%Lx=X'*Xclear;clc;train_path='..\Data\TrainingSet\';ph ...

  6. Linux Ptrace 详解

    转 https://blog.csdn.net/u012417380/article/details/60470075 Linux Ptrace 详解 2017年03月05日 18:59:58 阅读数 ...

  7. Robot Framework user guide

    http://robotframework.org/robotframework/latest/RobotFrameworkUserGuide.html

  8. python入门:if和else的基本用法

    #!/usr/bin/env python # -*- coding:utf-8 -*- #2.X用raw_input,3.X用input #if和else的基本用法 name = input(&qu ...

  9. STA basic

  10. python爬虫基础11-selenium大全5/8-动作链

    Selenium笔记(5)动作链 本文集链接:https://www.jianshu.com/nb/25338984 简介 一般来说我们与页面的交互可以使用Webelement的方法来进行点击等操作. ...