luoguP3690 【模板】Link Cut Tree (动态树)[LCT]

题目背景

动态树

题目描述

给定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

说明

数据范围: 



因为只是模板题吧。。在这里直接放上代码。。

关于LCT可以看论文:QTREE解法的一些研究

  1 #include<cstdio>
  2 #include<cstring>
  3 #include<iostream>
  4 using namespace std;
  5
  6 int read(){
  7     char ch;
  8     int re=0;
  9     bool flag=0;
 10     while((ch=getchar())!=‘-‘&&(ch<‘0‘||ch>‘9‘));
 11     ch==‘-‘?flag=1:re=ch-‘0‘;
 12     while((ch=getchar())>=‘0‘&&ch<=‘9‘)  re=re*10+ch-‘0‘;
 13     return flag?-re:re;
 14 }
 15
 16 struct Splay{
 17     int ch[2],xr,fa;
 18     bool rev;
 19 };
 20
 21 const int maxn=300005;
 22
 23 int n,m,top;
 24 int val[maxn],stk[maxn];
 25 Splay T[maxn];
 26
 27 inline void push_up(int x){  T[x].xr=T[T[x].ch[0]].xr^T[T[x].ch[1]].xr^val[x];   }
 28
 29 inline bool isroot(int x){
 30     return T[T[x].fa].ch[0]!=x&&T[T[x].fa].ch[1]!=x;
 31 }
 32
 33 inline void push_down(int x){
 34     if(T[x].rev){
 35         T[T[x].ch[0]].rev^=1;
 36         T[T[x].ch[1]].rev^=1;
 37         swap(T[x].ch[0],T[x].ch[1]);
 38         T[x].rev=0;
 39     }
 40 }
 41
 42 void rot(int x){
 43     int y=T[x].fa,z=T[y].fa,l,r;
 44     if(T[y].ch[0]==x)  l=0;
 45     else  l=1;
 46     r=l^1;
 47     T[x].fa=z;
 48     if(!isroot(y))  T[z].ch[T[z].ch[1]==y]=x;
 49     T[T[x].ch[r]].fa=y;
 50     T[y].ch[l]=T[x].ch[r];
 51     T[y].fa=x;
 52     T[x].ch[r]=y;
 53     push_up(y),push_up(x);
 54 }
 55
 56 void splay(int x){
 57     top=1;  stk[top]=x;
 58     for(int i=x;!isroot(i);i=T[i].fa)  stk[++top]=T[i].fa;
 59     for(int i=top;i;i--)  push_down(stk[i]);
 60     while(!isroot(x)){
 61         int y=T[x].fa,z=T[y].fa;
 62         if(!isroot(y)){
 63             if((T[y].ch[0]==x)^(T[z].ch[0]==y))  rot(x);
 64             else  rot(y);
 65         }
 66         rot(x);
 67     }
 68 }
 69
 70 void acc(int x){
 71     int t=0;
 72     while(x){
 73         splay(x);
 74         T[x].ch[1]=t;
 75         push_up(x);
 76         t=x;  x=T[x].fa;
 77     }
 78 }
 79
 80 void make_root(int x){
 81     acc(x);
 82     splay(x);
 83     T[x].rev^=1;
 84 }
 85
 86 int find(int x){
 87     acc(x);
 88     splay(x);
 89     while(T[x].ch[0])  x=T[x].ch[0];
 90     return x;
 91 }
 92
 93 void split(int x,int y){
 94     make_root(x);
 95     acc(y);
 96     splay(y);
 97 }
 98
 99 void cut(int x,int y){
100     split(x,y);
101     if(T[y].ch[0]==x)  T[y].ch[0]=0,T[x].fa=0;
102 }
103
104 void link(int x,int y){
105     make_root(x);
106     T[x].fa=y;
107 }
108
109 int main(){
110 //    freopen("temp.in","r",stdin);
111     n=read(),m=read();
112     for(int i=1;i<=n;i++){
113         val[i]=read();
114         T[i].xr=val[i];
115     }
116     int opt,x,y,xx,yy;
117     while(m--){
118         opt=read(),x=read(),y=read();
119         switch(opt){
120             case 0:{
121                 split(x,y);
122                 printf("%d\n",T[y].xr);
123                 break;
124             }
125             case 1:{
126                 xx=find(x),yy=find(y);
127                 if(xx!=yy)  link(x,y);
128                 break;
129             }
130             case 2:{
131                 xx=find(x),yy=find(y);
132                 if(xx==yy)  cut(x,y);
133                 break;
134             }
135             case 3:{
136                 acc(x);
137                 splay(x);
138                 val[x]=y;
139                 push_up(x);
140                 break;
141             }
142         }
143     }
144     return 0;
145 }
时间: 2024-10-14 12:16:39

luoguP3690 【模板】Link Cut Tree (动态树)[LCT]的相关文章

Link Cut Tree 动态树 小结

动态树有些类似 树链剖分+并查集 的思想,是用splay维护的 lct的根是动态的,"轻重链"也是动态的,所以并没有真正的轻重链 动态树的操作核心是把你要把 修改/询问/... 等等一系列的操作的树链放到一个splay里,然后用splay根据相对深度大小来维护这个树链 lct利用了splay的神奇性质,通过"认爹不认子"来达到记录多个子树的目的 lct的核心,access函数的意义是,在从这个点到它所在联通块中 相对深度最小的点 (可以理解为子树根) 的树链上,打通

P3690 Link Cut Tree (动态树)

干脆整个LCT模板吧. 缺个链上修改和子树操作,链上修改的话join(u,v)然后把v splay到树根再打个标记就好. 至于子树操作...以后有空的话再学(咕咕咕警告) 1 #include<bits/stdc++.h> 2 using namespace std; 3 typedef long long ll; 4 const int N=1e5+10; 5 int n,m,a[N],Xor[N],fa[N],ch[N][2],flp[N],sta[N],tp; 6 #define l(u

[模板]Link Cut Tree

传送门 Description 给定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. Solution \(Link\ Cut\ Tree\)模板题

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

P3690 [模板]Link Cut Tree (动态树) 题目背景 动态树 题目描述 给定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. 输入输出

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

P3690 [模板]Link Cut Tree (动态树) https://www.luogu.org/problemnew/show/P3690 分析: LCT模板 代码: 注意一下cut! 1 #include<cstdio> 2 #include<algorithm> 3 4 using namespace std; 5 6 const int N = 300100; 7 8 int val[N],fa[N],ch[N][2],rev[N],sum[N],st[N],top;

AC日记——【模板】Link Cut Tree 洛谷 P3690

[模板]Link Cut Tree 思路: LCT模板: 代码: #include <bits/stdc++.h> using namespace std; #define maxn 300005 int n,m,val[maxn]; int top,ch[maxn][2],f[maxn],xr[maxn],q[maxn],rev[maxn]; inline void in(int &now) { int if_z=1;now=0; char Cget=getchar(); while

hdu 5002 (动态树lct)

Tree Time Limit: 16000/8000 MS (Java/Others)    Memory Limit: 65536/65536 K (Java/Others)Total Submission(s): 920    Accepted Submission(s): 388 Problem Description You are given a tree with N nodes which are numbered by integers 1..N. Each node is a

动态树LCT小结

最开始看动态树不知道找了多少资料,总感觉不能完全理解.但其实理解了就是那么一回事...动态树在某种意思上来说跟树链剖分很相似,都是为了解决序列问题,树链剖分由于树的形态是不变的,所以可以通过预处理节点间的关系,将树转化成连续的区间,再加以其它的数据结构,便能以较快的速度处理序列的修改和查询. 而动态树的问题,是包括了树的合并和拆分操作.这个时候,通过预处理实现的静态树的序列算法不能满足我们的要求,于是我们需要一颗‘动态’的树,能在O(logN)的时间复杂度,处理所有操作. Splay实现的Lin

脑洞大开加偏执人格——可持久化treap版的Link Cut Tree

一直没有点动态树这个科技树,因为听说只能用Splay,用Treap的话多一个log.有一天脑洞大开,想到也许Treap也能从底向上Split.仔细思考了一下,发现翻转标记不好写,再仔细思考了一下,发现还是可以写的,只需要实时交换答案二元组里的两棵树,最后在吧提出来的访问节点放回去就行了.本着只学一种平衡树的想法,脑洞大开加偏执人格的开始写可持久化Treap版的Link Cut Tree... 写了才发现,常数硕大啊!!!代码超长啊!!!因为merge是从上到下,split从下到上,pushdow

hdu 5398 动态树LCT

GCD Tree Time Limit: 5000/2500 MS (Java/Others)    Memory Limit: 65536/65536 K (Java/Others)Total Submission(s): 415    Accepted Submission(s): 172 Problem Description Teacher Mai has a graph with n vertices numbered from 1 to n. For every edge(u,v),