LCT模板及详细讲解
来源:互联网 发布:淘宝店铺关闭怎么激活 编辑:程序博客网 时间:2024/05/18 02:28
Link cut tree
从一个例子引入:
bzoj1036
此题有两种解法,这里只提LCT的方法。
一棵树上有n个节点,有3个操作:
1、将节点u的权值改为t。
2、询问从点u到点v的路径上的节点的最大权值
3、询问从点u到点v的路径上的节点的权值和
如果学过树链剖分的话此题是可以轻易地解决的,可引入LCT解此题。
LCT换句话说就是多个splay树链来链去,连起来再断开。
其中最基础的操作-----Access,也是最不好理解的。
如果我讲的不能理解的话可以参考杨哲的论文《QTREE 解法的一些研究》
Access
如果节点v的子树中,最后被访问的节点在子树w中,则称w为v的Preferred Child,v到w这条边就是Preferred Edge,而由Preferred Edge 连成的路径为Preferred Path,所以,整棵树被划分成了若干条Preferred Path。
如果调用了Access(v),则v的父节点的Preferred Child就变成了v,这样应该可以很好理解Access操作了吧,如果不行可以看论文里的例子。
真实代码和伪代码有点不同。
void access(int x){ for(int t=0;x;t=x,x=fa[x]) splay(x),tr[x][1]=t,update(x);}
接下来介绍其他一些操作:
Makeroot(x):使x所在的splay树中把x作为根节点。
将x的父亲节点的Preferred Child 改为x,然后splay操作将x转到树根,同时rev[x]取反。
void makeroot(int x){ access(x);splay(x);rev[x]^=1;}
Link(x,y):将x节点与y节点连边。
将x节点变为根节点,然后让fa[x]=y;
void link(int x,int y){ makeroot(x);fa[x]=y;}
Split(x,y):将x到y的路径取出(分离)。
void split(int x,int y){ makeroot(x);access(y);splay(y);}
整体代码:
#include <queue>#include <cstdio>#include <iostream>#include <cstring>#include <algorithm>#include <cmath>#define N 30000+30#define ll long longusing namespace std;int read(){ int x=0,f=1;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,top,fa[N],tr[N][2],u[N],v[N],q[N];ll w[N],sum[N],mx[N];bool rev[N];bool isroot(int x){ return tr[fa[x]][0]!=x && tr[fa[x]][1]!=x;}void update(int x){ int l=tr[x][0],r=tr[x][1]; sum[x]=sum[l]+sum[r]+w[x]; mx[x]=max(w[x],max(mx[l],mx[r]));}void pushdown(int x){ int l=tr[x][0],r=tr[x][1]; if(rev[x]){ rev[x]^=1;rev[l]^=1;rev[r]^=1; swap(tr[x][0],tr[x][1]); }}inline void rotate(int x){ int f=fa[x],ff=fa[f],l,r; if(tr[f][0]==x) l=0;else l=1;r=l^1; if(!isroot(f)) tr[ff][tr[ff][1]==f]=x; fa[tr[x][r]]=f;fa[f]=x;fa[x]=ff; tr[f][l]=tr[x][r];tr[x][r]=f; update(f);update(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 f=fa[x],ff=fa[f]; if(!isroot(f)){ if(tr[f][0]==x ^ tr[ff][0]==f) rotate(x); else rotate(f); } rotate(x); }}void access(int x){ for(int t=0;x;t=x,x=fa[x]) splay(x),tr[x][1]=t,update(x);}void makeroot(int x){ access(x); splay(x); rev[x]^=1;}void link(int x,int y){ makeroot(x);fa[x]=y;}void split(int x,int y){ makeroot(x); access(y); splay(y);}int main(){ n=read();mx[0]=-(1e9); for(int i=1;i<n;i++) u[i]=read(),v[i]=read(); for(int i=1;i<=n;i++){ w[i]=read(); sum[i]=mx[i]=w[i]; } for(int i=1;i<n;i++) link(u[i],v[i]); m=read(); char ch[10]; int u,v; while(m--){ scanf("%s",ch); u=read();v=read(); if(ch[0]=='C'){ splay(u); w[u]=v; update(u); } if(ch[1]=='M') split(u,v),printf("%lld\n",mx[v]); if(ch[1]=='S') split(u,v),printf("%lld\n",sum[v]); } return 0;}比树链剖分慢qwq
这只是个开始,后面还有很多LCT的变形,这是裸的模板题。
阅读全文
1 0
- LCT模板及详细讲解
- lct模板
- LCT模板
- LCT模板
- 【模板】LCT
- 【模板】LCT
- LCT模板
- 【模板整合】LCT模板
- 扩展欧几里德模板及讲解
- LCT(模板题)BZOJ2049
- 【模板】LCT+理解
- 静态LCT标准模板
- LCT操作模板
- bzoj 2843 LCT模板
- bzoj 2049 LCT模板
- LCT模板题
- 动态树LCT 模板
- 【lct模板】bzoj2631: tree
- 解决Zepto.js轻扫手势和动画没作用
- 重载运算符=
- eclipse常用快捷键
- 基于canny边缘检测以及基于radon变换的矩形旋转矫正
- PAT 乙级 1032
- LCT模板及详细讲解
- 遗传算法(四)MATLAB GA工具箱使用 附解TSP问题
- JAVA设计模式之迭代器模式
- 面向对象的程序设计——(一)理解对象的属性以及属性的特性
- 无监督学习之K-均值算法分析与MATLAB代码实现
- 测试人员例会会议议题制定规范
- 初学素数筛选打表法
- 方法——猜字母小游戏
- java学习内容