首页 > 其他分享 >LCT-Link Cut Tree【模板】

LCT-Link Cut Tree【模板】

时间:2023-04-15 17:00:56浏览次数:46  
标签:LCT Cut int Tree void tr splay fa ls

动态树与LCT

LCT:Link Cut Tree
可以用来解决动态地连接和删除
结合树链剖分(实链剖分)和Splay树
“原树实链从上到下,对应Splay树从左到右”
把原树转化到辅助树上操作
而辅助树由若干个Splay树用虚边相连得来

题目描述

#include <bits/stdc++.h>
using namespace std;
#define fa(x) tr[x].fa
#define ls(x) tr[x].s[0]
#define rs(x) tr[x].s[1]
#define notroot(x) ls(fa(x))==x||rs(fa(x))==x //判断x不是某个Splay树的根 
//原树实链从上到下,对应splay树从左到右 

const int maxn=3e5+10;
int n,m; 
struct node{
  int s[2],fa,val,sum,tag;//tag是翻转懒标记 
}tr[maxn];

//pushup更新x的值
void pushup(int x){
  tr[x].sum=tr[x].val^tr[ls(x)].sum^tr[rs(x)].sum;
} 
//pushdown下放懒标记 
void pushdown(int x){
  if(tr[x].tag){
    swap(ls(x),rs(x));
    tr[ls(x)].tag^=1;
    tr[rs(x)].tag^=1;
    tr[x].tag=0;  	
  }
}
//rotate旋转Splay树 
void rotate(int x){
  int y=fa(x),z=fa(y);
  int k= rs(y)==x;
  if(notroot(y))//连x->z必须在最前面,否则后面y改变了就会影响虚边 
    tr[z].s[rs(z)==y]=x;
  fa(x)=z;
  tr[y].s[k]=tr[x].s[k^1];
  fa(tr[x].s[k^1])=y;
  tr[x].s[k^1]=y;
  fa(y)=x;
  pushup(y);pushup(x);
}
//pushall在每一次splay时都要更新要改变的点懒标记
void pushall(int x){
  if(notroot(x)) pushall(fa(x));
  pushdown(x);
} 
//splay把x旋转到Splay树的根 
void splay(int x){
  pushall(x);
  while(notroot(x)){
  	int y=fa(x),z=fa(y);
  	if(notroot(y))
  	  (ls(y)==x)^(ls(z)==y)?rotate(x):rotate(y);//折转底,直转中
	rotate(x); 
  }
} 
//access从x打一条通路到根 
void access(int x){
  for(int y=0;x;){
  	splay(x);
  	rs(x)=y;//把有用的虚边变成实边,把没用的实边变成虚边 
  	pushup(x);//更新x
	y=x,x=fa(x); 
  }
}
//makeroot换根 
void makeroot(int x){
  access(x);
  splay(x);//此时x在原树的最下面 
  tr[x].tag^=1;//让x作为原树中的根,对应splay树上左右翻转 
}
//split求x->y路径上异或和
void split(int x,int y){
  makeroot(x);
  access(y);
  splay(y);//此时y为根 
} 
//output输出
void output(int x,int y){
  split(x,y);
  printf("%d\n",tr[y].sum);
} 
//findroot找到x在原树上的根
int findroot(int x){
  access(x);
  splay(x);//此时x的根在这条链最下面
  while(ls(x))
    pushdown(x),x=ls(x);
  splay(x);//防止卡链
  return x; 
} 
//link连边 
void link(int x,int y){
  makeroot(x);
  if(findroot(y)!=x) fa(x)=y;//不能颠倒,因为x是一个splay的根而y不一定 
}
//cut断边 
void cut(int x,int y){
  makeroot(x);
  if(findroot(y)==x&&fa(y)==x&&!ls(y))//y要是一个splay的根 
    fa(y)=0,pushup(x);
} 
//change修改
void change(int x,int val){
  splay(x);
  tr[x].val=val;
  pushup(x);
} 

int main(){
  /*2023.4.15 hewanying P3690 【模板】动态树(Link Cut Tree) LCT*/ 
  scanf("%d%d",&n,&m);
  int op,x,y;
  for(int i=1;i<=n;i++) scanf("%d",&tr[i].val);
  for(int i=1;i<=m;i++){
  	scanf("%d%d%d",&op,&x,&y);
  	if(op==0) output(x,y);
  	if(op==1) link(x,y);
  	if(op==2) cut(x,y);
  	if(op==3) change(x,y);
  }
  return 0;
}
时间复杂度

和Splay一样 \(O(m \log_2 n)\)

标签:LCT,Cut,int,Tree,void,tr,splay,fa,ls
From: https://www.cnblogs.com/hewanying0622/p/17321421.html

相关文章

  • 【题解】Tree MST
    题面给定一棵\(n\)个节点的树,现有有一张完全图,两点\(x,y\)之间的边长为\(w_x+w_y+dis_{x,y}\),其中\(dis\)表示树上两点的距离。求完全图的最小生成树。\(n\leq2\times10^5\)。题解???神秘借鉴支配对的思想,点分治后将树中点权替换为\(dep_i+w_i\),选择点权最小的一个......
  • macOS Finder move & cut & copy & paste file All In One
    macOSFindermove&cut&copy&pastefileAllInOne鼠标拖动Drag&Drop快捷键shortcutsmacOSfindercut&copyfile快捷键CommandXmacOSfindercopyfile快捷键CommandCmacOSfindercopy&pastefile......
  • 两个循环搞定多级菜单列表递归成tree
    菜单类publicstaticclassMenu{Menu(Stringdata){String[]split=data.split("");this.id=Integer.valueOf(split[0]);this.name=split[1];this.pid=Integer.valueOf(split[2]);......
  • Codeforces Round #303 (Div. 2) E. Paths and Trees (最短路+变形最小生成树)
    题目地址:E.PathsandTrees模拟了一场CF,这场实在太水了。。边玩边做的。。最后半分钟交了一发E题。。不幸AK绝杀失败。。。。首先的思路肯定是先求最短路,把可能为最短路的边挑出来,然后第二步我本来写的是直接用无向图的最小生成树,于是绝杀失败。。。后来才发现这样是不行的。......
  • Codeforces Round #316 (Div. 2) D. Tree Requests (DFS序)
    题目地址:http://codeforces.com/contest/570/problem/D比赛的时候实在没想到DFS序,。。想到DFS序后,分别存起每个深度的所有节点的DFS序,处理出前缀异或和,然后二分找到两个端点,再异或一下,就求出了所求区间的异或和,由于偶数次的都被异或掉了,所以判断下奇数次数是否大于1即可。代码......
  • HDU 4812 D Tree (树上点分治)
    题目地址:HDU4812这题是13年南京区域赛的现场题。树分治思想。树分治的过程中记录下每个子树的所有到达根的路径的积,用best记录下每个积的最小端点,然后再枚举当前子树的每个积,然后用逆元的方法求出当积为k时所需要的另一个端点值,并更新答案。代码如下:#include<iostream>#......
  • SPOJ 375 QTREE系列-Query on a tree (树链剖分)
    题目地址:SPOJ375树链剖分第一发!果然是个貌似很高级的数据结构,其实就是把树的边从树形结构转化成了线性结构,从而可以用线段树或树状数组之类的数据结构进行快速维护。从而将时间缩到n*log(2*n).这题用的线段树维护的。代码如下:#include<iostream>#include<string.h......
  • POJ 3237 Tree (树链剖分)
    题目地址:POJ3237这题用了一下午。。本来一直认为max和min两个数组是不用改的,只需要改lazy数组,然后在查询的时候利用lazy标记来返回max或-min,后来发现错的很严重。。这题要在pushdown中修改max和min数组,从而实现最大值取反。代码如下:#include<iostream>#include<strin......
  • Element Plus Tree 树 回显
     <el-form-itemlabel="菜单权限">       <el-tree:data="navList"ref="treeRef"  node-key="menuId"highlight-current=“true”:props="defaultProps" @check="checked" show-checkboxcl......
  • TreeMap源码
          常见面试题:    ......