我终于理解了 \(LCT\)!!!想不到小蒟蒻有一天理解了!!!

1、【模板】Link Cut Tree

存个板子

#include <bits/stdc++.h>
using namespace std;
const int maxn=300000+10;
int n,m,a[maxn],ch[maxn][2],fa[maxn],val[maxn],sta[maxn],top;
bool rev[maxn]; inline void reverse(int x){
swap(ch[x][0],ch[x][1]);
rev[x]^=1;
}
inline void pushup(int x){
val[x]=val[ch[x][0]]^val[ch[x][1]]^a[x];
}
inline void pushdown(int x){
if(rev[x]){
rev[x]=0;
if(ch[x][0]) reverse(ch[x][0]);
if(ch[x][1]) reverse(ch[x][1]);
}
}
inline bool nrt(int x){
return ch[fa[x]][0]==x||ch[fa[x]][1]==x;
}
inline void rotate(int x){
int y=fa[x],z=fa[y],k=(x==ch[y][1]),u=ch[x][k^1];
if(nrt(y)) ch[z][ch[z][1]==y]=x;
ch[y][k]=u;ch[x][k^1]=y;
if(u) fa[u]=y;fa[y]=x;fa[x]=z;
val[x]=val[y];pushup(y);
}
inline void splay(int x){
int y,z;top=0;
for(y=x;nrt(y);y=fa[y]) sta[top++]=y;
pushdown(y);
while(top) pushdown(sta[--top]);
while(nrt(x)){
y=fa[x],z=fa[y];
if(nrt(y)) rotate((ch[y][1]==x)^(ch[z][1]==y)?x:y);
rotate(x);
}
}
inline void access(int x){
int y=0;
for(;x;y=x,x=fa[x])
splay(x),ch[x][1]=y,pushup(x);
}
inline void makeroot(int x){
access(x),splay(x),reverse(x);
}
inline int findroot(int x){
access(x),splay(x);
for(;ch[x][0];x=ch[x][0]) pushdown(x);
return x;
}
inline void split(int x,int y){
makeroot(x),access(y),splay(y);
}
inline void link(int x,int y){
makeroot(x);
if(findroot(y)!=x)
fa[x]=y,pushup(y);
}
inline void cut(int x,int y){
makeroot(x);
if(findroot(y)==x&&fa[x]==y&&!ch[x][1])
fa[x]=ch[y][0]=0,pushup(y);
}
inline int read(){
register int x=0,f=1;char ch=getchar();
while(!isdigit(ch)){if(ch=='-')f=-1;ch=getchar();}
while(isdigit(ch)){x=(x<<3)+(x<<1)+ch-'0';ch=getchar();}
return (f==1)?x:-x;
} int main()
{
n=read(),m=read();
for(int i=1;i<=n;i++){
val[i]=a[i]=read();
fa[i]=ch[i][0]=ch[i][1]=0;
}
int opt,x,y;
for(int i=1;i<=m;i++){
opt=read(),x=read(),y=read();
if(opt==0) split(x,y),printf("%d\n",val[y]);
if(opt==1) link(x,y);
if(opt==2) cut(x,y);
if(opt==3) splay(x),a[x]=y,pushup(x);
}
return 0;
}

2、[COCI 2009] OTOCI / 极地旅行社

其实就是 \(pushup\) 改了一下

\(Code\ Below:\)

#include <bits/stdc++.h>
using namespace std;
const int maxn=30000+10;
int n,q,a[maxn],ch[maxn][2],fa[maxn],val[maxn],sta[maxn],top;
bool rev[maxn]; inline int read(){
register int x=0,f=1;char ch=getchar();
while(!isdigit(ch)){if(ch=='-')f=-1;ch=getchar();}
while(isdigit(ch)){x=(x<<3)+(x<<1)+ch-'0';ch=getchar();}
return (f==1)?x:-x;
}
inline void reverse(int x){
swap(ch[x][0],ch[x][1]);
rev[x]^=1;
}
inline void pushup(int x){
val[x]=val[ch[x][0]]+val[ch[x][1]]+a[x];
}
inline void pushdown(int x){
if(rev[x]){
rev[x]=0;
if(ch[x][0]) reverse(ch[x][0]);
if(ch[x][1]) reverse(ch[x][1]);
}
}
inline bool nrt(int x){
return ch[fa[x]][0]==x||ch[fa[x]][1]==x;
}
inline void rotate(int x){
int y=fa[x],z=fa[y],k=(x==ch[y][1]),u=ch[x][k^1];
if(nrt(y)) ch[z][ch[z][1]==y]=x;
ch[y][k]=u;ch[x][k^1]=y;
if(u) fa[u]=y;fa[y]=x;fa[x]=z;
val[x]=val[y];pushup(y);
}
inline void splay(int x){
int y,z;top=0;
for(y=x;nrt(y);y=fa[y]) sta[top++]=y;
pushdown(y);
while(top) pushdown(sta[--top]);
while(nrt(x)){
y=fa[x],z=fa[y];
if(nrt(y)) rotate((ch[y][1]==x)^(ch[z][1]==y)?x:y);
rotate(x);
}
}
inline void access(int x){
int y=0;
for(;x;y=x,x=fa[x])
splay(x),ch[x][1]=y,pushup(x);
}
inline void makeroot(int x){
access(x),splay(x),reverse(x);
}
inline int findroot(int x){
access(x),splay(x);
for(;ch[x][0];x=ch[x][0]) pushdown(x);
return x;
}
inline void split(int x,int y){
makeroot(x),access(y),splay(y);
}
inline int link(int x,int y){
makeroot(x);
if(findroot(y)!=x){
fa[x]=y,pushup(y);
return 1;
}
return 0;
}
inline void cut(int x,int y){
makeroot(x);
if(findroot(y)==x&&fa[x]==y&&!ch[x][1])
fa[x]=ch[y][0]=0,pushup(y);
} int main()
{
n=read();
for(int i=1;i<=n;i++)
val[i]=a[i]=read();
char opt[20];int x,y;
q=read();
for(int i=1;i<=q;i++){
scanf("%s",opt);
x=read(),y=read();
if(opt[0]=='b'){
if(link(x,y)) printf("yes\n");
else printf("no\n");
}
if(opt[0]=='p'){
splay(x),a[x]=y,pushup(x);
}
if(opt[0]=='e'){
makeroot(x);
if(findroot(y)!=x)
printf("impossible\n");
else split(x,y),printf("%d\n",val[y]);
}
}
return 0;
}

3、[WC2006]水管局长

删边操作不好处理,所以倒过来。

动态查询最大边权的最小值,先做一遍 \(Kruskal\),然后每次选一条最大的边权,如果当前加边的边权比最大的边权小,那么 \(Cut\) 掉原来的边然后 \(Link\) 一下现在的边。

边权不好处理,还要转化成点权,用虚点法。

\(Code\ Below:\)

#include <bits/stdc++.h>
#define pii pair<int,int>
using namespace std;
const int maxn=1000000+10;
int n,m,Q,ch[maxn][2],fa[maxn],val[maxn],Max[maxn],sta[maxn],f[maxn],ans[maxn],top;
bool rev[maxn],vis[maxn];
struct Edge{
int x,y,w;
}e[maxn];
struct Query{
int op,x,y,id;
}q[maxn];
map<pii,int> mp;
bool cmp(Edge a,Edge b){
return a.w<b.w;
}
inline int read(){
register int x=0,f=1;char ch=getchar();
while(!isdigit(ch)){if(ch=='-')f=-1;ch=getchar();}
while(isdigit(ch)){x=(x<<3)+(x<<1)+ch-'0';ch=getchar();}
return (f==1)?x:-x;
}
inline void reverse(int x){
swap(ch[x][0],ch[x][1]);
rev[x]^=1;
}
inline void pushup(int x){
Max[x]=x;
if(val[Max[ch[x][0]]]>val[Max[x]]) Max[x]=Max[ch[x][0]];
if(val[Max[ch[x][1]]]>val[Max[x]]) Max[x]=Max[ch[x][1]];
}
inline void pushdown(int x){
if(rev[x]){
rev[x]=0;
if(ch[x][0]) reverse(ch[x][0]);
if(ch[x][1]) reverse(ch[x][1]);
}
}
inline bool nrt(int x){
return x==ch[fa[x]][0]||x==ch[fa[x]][1];
}
inline void rotate(int x){
int y=fa[x],z=fa[y],k=(x==ch[y][1]),u=ch[x][k^1];
if(nrt(y)) ch[z][ch[z][1]==y]=x;
ch[y][k]=u;ch[x][k^1]=y;
if(u) fa[u]=y;fa[y]=x;fa[x]=z;
pushup(y);pushup(x);
}
inline void splay(int x){
int y,z;top=0;
for(y=x;nrt(y);y=fa[y]) sta[++top]=y;
pushdown(y);
while(top) pushdown(sta[top--]);
while(nrt(x)){
y=fa[x],z=fa[y];
if(nrt(y)) rotate((x==ch[y][1])^(y==ch[z][1])?x:y);
rotate(x);
}
}
inline void access(int x){
int y=0;
for(;x;y=x,x=fa[x])
splay(x),ch[x][1]=y,pushup(x);
}
inline void makeroot(int x){
access(x),splay(x),reverse(x);
}
inline int findroot(int x){
access(x),splay(x);
for(;ch[x][0];x=ch[x][0]) pushdown(x);
return x;
}
inline void split(int x,int y){
makeroot(x),access(y),splay(y);
}
inline void link(int x,int y){
makeroot(x);
if(findroot(y)!=x)
fa[x]=y,pushup(y);
}
inline void cut(int x,int y){
makeroot(x);
if(findroot(y)==x&&fa[x]==y&&!ch[y][1])
fa[x]=ch[y][0]=0,pushup(y);
}
int find(int x){
return (x==f[x])?x:f[x]=find(f[x]);
} int main()
{
n=read(),m=read(),Q=read();
for(int i=1;i<=m;i++){
e[i].x=read(),e[i].y=read(),e[i].w=read();
if(e[i].x>e[i].y) swap(e[i].x,e[i].y);
}
sort(e+1,e+m+1,cmp);
for(int i=1;i<=m;i++){
mp[make_pair(e[i].x,e[i].y)]=i;
val[i+n]=e[i].w;Max[i+n]=i+n;
}
for(int i=1;i<=Q;i++){
q[i].op=read(),q[i].x=read(),q[i].y=read();
if(q[i].op==2){
if(q[i].x>q[i].y) swap(q[i].x,q[i].y);
q[i].id=mp[make_pair(q[i].x,q[i].y)];
vis[q[i].id]=1;
}
}
int x,y,t,a,b,tot=0;
for(int i=1;i<=n;i++) f[i]=i;
for(int i=1;i<=m;i++){
if(!vis[i]){
x=e[i].x;y=e[i].y;
a=find(x);b=find(y);
if(a!=b){
link(x,i+n);link(y,i+n);
f[a]=b;tot++;
if(tot==n-1) break;
}
}
}
for(int i=Q;i>=1;i--){
x=q[i].x;y=q[i].y;
if(q[i].op==1){
split(x,y);ans[i]=val[Max[y]];
}
else {
split(x,y);t=Max[y];
if(val[q[i].id+n]<val[t]){
cut(e[t-n].x,t);cut(e[t-n].y,t);
link(x,q[i].id+n);link(y,q[i].id+n);
}
}
}
for(int i=1;i<=Q;i++)
if(q[i].op==1) printf("%d\n",ans[i]);
return 0;
}

4、[NOI2014]魔法森林

边权先按 \(b\) 排序,然后维护一个 \(a\) 的最大边权的最小值,把边权转换成点权。

\(Code\ Below:\)

// luogu-judger-enable-o2
#include <bits/stdc++.h>
using namespace std;
const int maxn=200000+10;
const int inf=0x3f3f3f3f;
int n,m,ch[maxn][2],fa[maxn],val[maxn],Max[maxn],sta[maxn],top,ans=inf;
bool rev[maxn]; struct Edge{
int x,y,a,b;
}e[maxn]; bool cmp(Edge x,Edge y){
return x.b<y.b;
} inline int read(){
register int x=0,f=1;char ch=getchar();
while(!isdigit(ch)){if(ch=='-')f=-1;ch=getchar();}
while(isdigit(ch)){x=(x<<3)+(x<<1)+ch-'0';ch=getchar();}
return (f==1)?x:-x;
} inline void reverse(int x){
swap(ch[x][0],ch[x][1]);
rev[x]^=1;
}
inline void pushup(int x){
Max[x]=x;
if(val[Max[ch[x][0]]]>val[Max[x]]) Max[x]=Max[ch[x][0]];
if(val[Max[ch[x][1]]]>val[Max[x]]) Max[x]=Max[ch[x][1]];
}
inline void pushdown(int x){
if(rev[x]){
rev[x]=0;
if(ch[x][0]) reverse(ch[x][0]);
if(ch[x][1]) reverse(ch[x][1]);
}
}
inline bool nrt(int x){
return x==ch[fa[x]][0]||x==ch[fa[x]][1];
}
inline void rotate(int x){
int y=fa[x],z=fa[y],k=(x==ch[y][1]),u=ch[x][k^1];
if(nrt(y)) ch[z][ch[z][1]==y]=x;
ch[y][k]=u;ch[x][k^1]=y;
if(u) fa[u]=y;fa[y]=x;fa[x]=z;
pushup(y);pushup(x);
}
inline void splay(int x){
int y,z;top=0;
for(y=x;nrt(y);y=fa[y]) sta[++top]=y;
pushdown(y);
while(top) pushdown(sta[top--]);
while(nrt(x)){
y=fa[x],z=fa[y];
if(nrt(y)) rotate((x==ch[y][1])^(y==ch[z][1])?x:y);
rotate(x);
}
}
inline void access(int x){
int y=0;
for(;x;y=x,x=fa[x])
splay(x),ch[x][1]=y,pushup(x);
}
inline int findroot(int x){
access(x),splay(x);
for(;ch[x][0];x=ch[x][0]) pushdown(x);
return x;
}
inline void makeroot(int x){
access(x),splay(x),reverse(x);
}
inline int split(int x,int y){
makeroot(x),access(y),splay(y);
return Max[y];
}
inline void link(int x,int y){
makeroot(x);
if(findroot(y)!=x)
fa[x]=y,pushup(y);
}
inline void cut(int x,int y){
makeroot(x);
if(findroot(y)==x&&fa[x]==y&&!ch[y][1])
fa[x]=ch[y][0]=0,pushup(y);
} int main()
{
n=read(),m=read();
for(int i=1;i<=m;i++)
e[i].x=read(),e[i].y=read(),e[i].a=read(),e[i].b=read();
sort(e+1,e+m+1,cmp);
for(int i=1;i<=m;i++){
val[i+n]=e[i].a;
Max[i+n]=i+n;
}
int x,y,t;bool flag=0;
for(int i=1;i<=m;i++){
x=e[i].x;y=e[i].y;flag=1;
if(findroot(x)==findroot(y)){
t=split(x,y);
if(val[t]>e[i].a) cut(e[t-n].x,t),cut(e[t-n].y,t);
else flag=0;
}
if(flag) link(x,i+n),link(y,i+n);
if(findroot(1)==findroot(n)) ans=min(ans,e[i].b+val[split(1,n)]);
}
printf("%d\n",(ans==inf)?-1:ans);
return 0;
}

[学习笔记]Link-Cut Tree的更多相关文章

  1. Link Cut Tree学习笔记

    从这里开始 动态树问题和Link Cut Tree 一些定义 access操作 换根操作 link和cut操作 时间复杂度证明 Link Cut Tree维护链上信息 Link Cut Tree维护子 ...

  2. 学习笔记:Link Cut Tree

    模板题 原理 类似树链剖分对重儿子/长儿子剖分,Link Cut Tree 也做的是类似的链剖分. 每个节点选出 \(0 / 1\) 个儿子作为实儿子,剩下是虚儿子.对应的边是实边/虚边,虚实时可以进 ...

  3. link cut tree 入门

    鉴于最近写bzoj还有51nod都出现写不动的现象,决定学习一波厉害的算法/数据结构. link cut tree:研究popoqqq那个神ppt. bzoj1036:维护access操作就可以了. ...

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

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

  5. Codeforces Round #339 (Div. 2) A. Link/Cut Tree 水题

    A. Link/Cut Tree 题目连接: http://www.codeforces.com/contest/614/problem/A Description Programmer Rostis ...

  6. Link/cut Tree

    Link/cut Tree 一棵link/cut tree是一种用以表示一个森林,一个有根树集合的数据结构.它提供以下操作: 向森林中加入一棵只有一个点的树. 将一个点及其子树从其所在的树上断开. 将 ...

  7. 洛谷P3690 Link Cut Tree (模板)

    Link Cut Tree 刚开始写了个指针版..调了一天然后放弃了.. 最后还是学了黄学长的板子!! #include <bits/stdc++.h> #define INF 0x3f3 ...

  8. bzoj2049 [Sdoi2008]Cave 洞穴勘测 link cut tree入门

    link cut tree入门题 首先说明本人只会写自底向上的数组版(都说了不写指针.不写自顶向下QAQ……) 突然发现link cut tree不难写... 说一下各个函数作用: bool isro ...

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

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

  10. [CodeForces - 614A] A - Link/Cut Tree

    A - Link/Cut Tree Programmer Rostislav got seriously interested in the Link/Cut Tree data structure, ...

随机推荐

  1. Controller异步模式

    转载: https://blog.csdn.net/yingxiake/article/details/51193319 因为服务器请求处理线程的总数是有限的,如果类似的请求多了,所有的处理线程处于阻 ...

  2. 2018.11.02 NOIP模拟 飞越行星带(最小生成树/二分+并查集)

    传送门 发现题目要求的就是从下到上的瓶颈路. 画个图出来发现跟去年noipnoipnoip提高组的奶酪差不多. 于是可以二分宽度+并查集检验,或者直接求瓶颈. 代码

  3. php mysqli 链接数据库 CURD 增改查删

    <?php function println($msg) { echo "<br>"; echo $msg; } $mysql_server_name = &qu ...

  4. Edifact 95B报文解读

    PART 1 INTRODUCTION D100_D.95B PART 2 UNIFORM RULES OF CONDUCT FOR INTERCHANGE PART2_D.ZIP(1) OF TRA ...

  5. MyGeneration使用概述

    1.首先要连接数据库,第一次启动myG的时候会弹出default settings对话框,以后也可以在Edit-default settings里面修改.default settings有3个tabs ...

  6. C#控件之:进度条(ProgressBar)

    一.重绘进度条 public class CustomProgressBar:ProgressBar { public CustomProgressBar() { this.SetStyle(Cont ...

  7. MIT Molecular Biology 笔记2 DNA的突变和修复

    视频  https://www.bilibili.com/video/av7973580?from=search&seid=16993146754254492690 教材 Molecular ...

  8. bzoj2893(费用流)

    先缩点,然后拆点,其实是很经典的一种操作,把不好做的点拆成边,然后我一开始想的是网络流,答案当然是增广次数, 但可以发现跑网络流的话不同的跑法增广次数不一样,不太好找最小的.我们可以换一种神奇的思路, ...

  9. gcc和vs在c的一些区别

    1.switch中每个标签后面的命令在gcc中需要{}括起来以指明作用域. 2._itoa是非标准的c和c++扩展函数,在linux下可以使用sprintf(string,   "%d &q ...

  10. Different timers in .net

    Multi-threads timers: System.Threading.Timer and System.Timers.Timer (.net framework): App will hand ...