模板linkcuttree(动态树)

Z-Y-Y-S Z-Y-Y-S     2022-10-09     357

关键词:

题目描述

给定N个点以及每个点的权值,要你处理接下来的M个操作。操作有4种。操作从0到3编号。点从1到N编号。

0:后接两个整数(x,y),代表询问从x到y的路径上的点的权值的xor和。保证x到y是联通的。

1:后接两个整数(x,y),代表连接x到y,若x到Y已经联通则无需连接。

2:后接两个整数(x,y),代表删除边(x,y),不保证边(x,y)存在。

3:后接两个整数(x,y),代表将点X上的权值变成Y。

输入输出格式

输入格式:

第1行两个整数,分别为N和M,代表点数和操作数。

第2行到第N+1行,每行一个整数,整数在[1,10^9]内,代表每个点的权值。

第N+2行到第N+M+1行,每行三个整数,分别代表操作类型和操作所需的量。

输出格式:

对于每一个0号操作,你须输出X到Y的路径上点权的Xor和。

输入输出样例

输入样例#1: 复制
3 3 
1
2
3
1 1 2
0 1 2 
0 1 1
输出样例#1: 复制
3
1

说明

数据范围: 1≤N,M≤3⋅105

算法原理提供可靠网址:

zyys

这道题用到的技巧:

 

找根:$makeroot(o)$后一直往左走。最后一个节点就是根。(理由:由于$LCT$中$splay$的性质:按深度作为键值);

 

判断是否之间有边:再$cut$之前,判断根的左儿子是否是另外一个点。(理由:若存在边,则包含这条边的$splay$只有两个节点)。

  1 #include<iostream>
  2 #include<cstdio>
  3 #include<cstring>
  4 #include<algorithm>
  5 #include<cmath>
  6 #include<queue>
  7 using namespace std;
  8 int xr[300005],ch[300005][2],val[300005],pre[300005],n,m;
  9 bool isrt[300005],rev[300005];
 10 void pushup(int o)
 11 {
 12   if (!o) return;
 13   xr[o]=xr[ch[o][0]]^xr[ch[o][1]]^val[o];
 14 }
 15 void pushdown(int o)
 16 {
 17   if (!o) return;
 18   if (rev[o])
 19     {
 20       int ls=ch[o][0],rs=ch[o][1];
 21       if (ls)
 22     {
 23       rev[ls]^=1;
 24       swap(ch[ls][0],ch[ls][1]);
 25     }
 26       if (rs)
 27     {
 28       rev[rs]^=1;
 29       swap(ch[rs][0],ch[rs][1]);
 30     }
 31       rev[o]=0;
 32     }
 33 }
 34 void push(int o)
 35 {
 36   if (isrt[o]==0)
 37       push(pre[o]);
 38   pushdown(o);
 39 }
 40 void rotate(int o,bool kind)
 41 {
 42   int p=pre[o];
 43   ch[p][!kind]=ch[o][kind];pre[ch[o][kind]]=p;
 44   if (isrt[p]) isrt[o]=1,isrt[p]=0;
 45   else ch[pre[p]][ch[pre[p]][1]==p]=o;
 46   pre[o]=pre[p];
 47   ch[o][kind]=p;pre[p]=o;
 48   pushup(p);pushup(o);
 49 }
 50 void splay(int o)
 51 {
 52   push(o);
 53   while (isrt[o]==0)
 54     {
 55       if (isrt[pre[o]])
 56     rotate(o,ch[pre[o]][0]==o);
 57       else
 58     {
 59       int p=pre[o],kind=ch[pre[p]][0]==p;
 60       if (ch[p][kind]==o)
 61         rotate(o,!kind),rotate(o,kind);
 62       else rotate(p,kind),rotate(o,kind);
 63     }
 64     }
 65 }
 66 void access(int o)
 67 {
 68   int y=0;
 69   while (o)
 70     {
 71       splay(o);
 72       //xr[o]^=xr[ch[o][1]];
 73       isrt[ch[o][1]]=1;isrt[ch[o][1]=y]=0;
 74       pushup(o);
 75       o=pre[y=o];
 76     }
 77 }
 78 void makeroot(int o)
 79 {
 80   access(o);
 81   splay(o);
 82   rev[o]^=1;
 83   swap(ch[o][0],ch[o][1]);
 84 }
 85 int find(int o)
 86 {
 87   makeroot(o);
 88   access(o);splay(o);
 89   while (ch[o][0])
 90     {
 91       o=ch[o][0];
 92     }
 93   return o;
 94 }
 95 void link(int x,int y)
 96 {
 97   makeroot(x);
 98   pre[x]=y;
 99 }
100 void cut(int x,int y)
101 {
102   makeroot(x);access(y);splay(y);
103   if (ch[y][0]!=x) return;
104   pre[x]=0;
105   ch[y][0]=0;
106   isrt[x]=1;
107   pushup(y);
108 }
109 int main()
110 {int i,c,x,y;
111   cin>>n>>m;
112   for (i=1;i<=n;i++)
113     {
114       scanf("%d",&val[i]);
115       xr[i]=val[i];isrt[i]=1;
116     }
117   for (i=1;i<=m;i++)
118     {
119       scanf("%d%d%d",&c,&x,&y);
120       if (c==0)
121     {
122       makeroot(y);
123       access(x);
124       splay(x);
125       printf("%d
",xr[x]);
126     }
127       else if (c==1)
128     {
129       int p=find(x),q=find(y);
130       if (p!=q) link(x,y);
131     }
132       else if (c==2)
133     {
134       cut(x,y);
135     }
136       else if (c==3)
137     {
138       val[x]=y;
139       makeroot(x);
140       pushup(x);
141     }
142     }
143 }

 

luogup3690模板linkcuttree(动态树)

#include<iostream>#include<cstring>#include<algorithm>#include<cmath>#include<cstdlib>#include<climits>#include<stack>#include<vector>#include<queue& 查看详情

luogu3690模板linkcuttree(动态树)

题目luogu3690硫硼作者想提醒大家,WA了TLE了RE了的,也许只是主函数写错了代码#include<iostream>#include<cstdio>#include<cmath>#include<algorithm>#include<cstdlib>#include<cstring>usingnamespacestd 查看详情

模板linkcuttree(动态树)

题目描述给定N个点以及每个点的权值,要你处理接下来的M个操作。操作有4种。操作从0到3编号。点从1到N编号。0:后接两个整数(x,y),代表询问从x到y的路径上的点的权值的xor和。保证x到y是联通的... 查看详情

luogup3690模板linkcuttree(动态树)[lct]

题目背景动态树题目描述给定N个点以及每个点的权值,要你处理接下来的M个操作。操作有4种。操作从0到3编号。点从1到N编号。0:后接两个整数(x,y),代表询问从x到y的路径上的点的权值的xor和。保证... 查看详情

数据结构专题-学习笔记:linkcuttree动态树

1.前言LinkCutTree动态树,简称LCT,是一种维护动态森林的数据结构。前置知识:Splay。2.LCT例题:P3690【模板】动态树(LinkCutTree)2.1实链剖分实链剖分也是一种对树的剖分方式,类似于重链剖分和长链剖分,其将一棵树上的边,随... 查看详情

p3690linkcuttree(动态树)

干脆整个LCT模板吧。缺个链上修改和子树操作,链上修改的话join(u,v)然后把vsplay到树根再打个标记就好。至于子树操作...以后有空的话再学(咕咕咕警告)1#include<bits/stdc++.h>2usingnamespacestd;3typedeflonglongll;4constintN=1e5+10;5intn,m,a[N],X... 查看详情

p3690模板linkcuttree(动态树)(代码片段)

哇,做梦也没想到我居然能写LCT题意:给定n个点以及每个点的权值,要你处理接下来的m个操作。操作有4种。操作从0到3编号。点从1到n编号。0:后接两个整数(x,y),代表询问从x到y的路径上的点的权值的xor和。保证x到y是联通... 查看详情

刷题洛谷p3690模板linkcuttree(动态树)(代码片段)

题目背景动态树题目描述给定n个点以及每个点的权值,要你处理接下来的m个操作。操作有4种。操作从0到3编号。点从1到n编号。0:后接两个整数(x,y),代表询问从x到y的路径上的点的权值的xor和。保证x到y是联通的。1:后接两... 查看详情

lct(linkcuttree)动态树(代码片段)

模板参考:https://blog.csdn.net/saramanda/article/details/55253627几个知识点:1、LCT中用Splay维护链,这些Splay叫做“辅助树“。辅助树以它上面每个节点的深度为关键字维护,就是辅助树中每个节点左儿子的深度小于当前节点的深度... 查看详情

p3690模板linkcuttree(动态树)(代码片段)

P3690【模板】LinkCutTree(动态树)注意:不要把$fa[x]$和$nrt(x)$混在一起!#include<cstdio>voidswap(int&a,int&b)a^=b^=a^=b;#defineN300005intn,m,s[N],v[N],ch[2][N],fa[N],rev[N];#definelcch[0][x]#definercch[1][x]boolnrt(intx)returnch[0][fa[x]]==x||ch[1][fa[x]]==x;voidu... 查看详情

linkcuttree学习笔记

从这里开始动态树问题和LinkCutTree一些定义access操作换根操作link和cut操作时间复杂度证明LinkCutTree维护链上信息LinkCutTree维护子树信息小结动态树问题和LinkCutTree  动态树问题是一类要求维护一个有根树森林,支持对树的分割,... 查看详情

linkcuttree动态树小结(代码片段)

动态树有些类似树链剖分+并查集的思想,是用splay维护的lct的根是动态的,"轻重链"也是动态的,所以并没有真正的轻重链动态树的操作核心是把你要把修改/询问/...等等一系列的操作的树链放到一个splay里,然后用splay根据相对... 查看详情

p3690模板linkcuttree(动态树)(代码片段)

LCTLCT即Link-Cut-Tree维护一个森林,支持很多操作,比如:维护链上信息(min,max,sum,xor。。。。。。)换根动态维护联通性维护子树信息概念虚边:连接儿子与父亲,儿子记录父亲,父亲不记录儿子(父不认子)实边:父子互... 查看详情

洛谷p3690模板linkcuttree(lct)(代码片段)

题目背景动态树题目描述给定n个点以及每个点的权值,要你处理接下来的m个操作。操作有4种。操作从0到3编号。点从1到n编号。0:后接两个整数(x,y),代表询问从x到y的路径上的点的权值的xor和。保证x到y是联通的。1:后接两... 查看详情

动态树模板(代码片段)

LinkCutTree:#include<bits/stdc++.h>#defineL(x)T[(x)].son[0]#defineR(x)T[(x)].son[1]#definefa(x)T[(x)].fausingnamespacestd;constintN=300050;intstk[N];intn,m;structTreeintson[2],fa;intval,siz,Xor;booltag;T[N];boolisroot(intx)return(L(fa(x))==x||R(fa(x))==x)==0;voidpushup(intx)T[x].Xor=T[L(x)].Xo... 查看详情

ac日记——模板linkcuttree洛谷p3690

【模板】LinkCutTree 思路:  LCT模板; 代码:#include<bits/stdc++.h>usingnamespacestd;#definemaxn300005intn,m,val[maxn];inttop,ch[maxn][2],f[maxn],xr[maxn],q[maxn],rev[maxn];inlinevoidin(int&now 查看详情

linkcuttree求最小生成树(代码片段)

对边建点,原图中的边转化为点的点-边的点-点的点于是用LCT维护连通关系,并支持查询最大值位置即可#include<bits/stdc++.h>usingnamespacestd;constintN=300005;intn,m,val[N],t1,t2,t3;namespacelct inttop,q[N],ch[N][2],fa[N],rev[N]; intmx[N]; inlin 查看详情

bzoj-3779重组病毒linkcuttree+线段树+dfs序

3779:重组病毒TimeLimit: 20Sec  MemoryLimit: 512MBSubmit: 224  Solved: 95[Submit][Status][Discuss]Description黑客们通过对已有的病毒反编译,将许多不同的病毒重组,并重新编译出了新型的重组病毒。这种病毒的繁殖和... 查看详情