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。

输入输出格式

输入格式:

第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\ \leq\ N\ \leq\ 3\ \times\ 10^5\)

LCT模板题。洛谷上有点卡常。。神TM插入的时候要按顺序插。。

#include <iostream>
#include <cstdio>
#include <cstring>
#include <cstdlib>
#include <algorithm>
#include <queue>
#include <vector>
#include <map>
#include <string>
#include <cmath>
#include <sstream>
#define min(a, b) ((a) < (b) ? (a) : (b))
#define max(a, b) ((a) > (b) ? (a) : (b))
#define abs(a) ((a) < 0 ? (-1 * (a)) : (a))
template<class T>
inline void swap(T &a, T &b)
{
    T tmp = a;a = b;b = tmp;
}
inline void read(int &x)
{
    x = 0;char ch = getchar(), c = ch;
    while(ch < '0' || ch > '9') c = ch, ch = getchar();
    while(ch <= '9' && ch >= '0') x = x * 10 + ch - '0', ch = getchar();
    if(c == '-') x = -x;
}
const int INF = 0x3f3f3f3f;
const int MAXN = 300000 + 10;
int ch[MAXN][2], fa[MAXN], data[MAXN], sum[MAXN], lazy[MAXN];
inline void pushup(int x){sum[x] = data[x] ^ sum[ch[x][0]] ^ sum[ch[x][1]];}
inline int son(int x){return x == ch[fa[x]][1];}
inline void rever(int x){lazy[x] ^= 1, swap(ch[x][0], ch[x][1]);}
inline void pushdown(int x){if(lazy[x])lazy[x] = 0, rever(ch[x][0]), rever(ch[x][1]);}
inline int isroot(int x){return ch[fa[x]][1] != x && ch[fa[x]][0] != x;}
void dfs(int x){if(x)dfs(fa[x]),pushdown(x);}
void rotate(int x)
{
    int y = fa[x], z = fa[y], b = son(x), c = son(y), a = ch[x][!b];
    if(!isroot(y) && z) ch[z][c] = x; fa[x] = z;
    if(a) fa[a] = y;ch[y][b] = a;
    ch[x][!b] = y, fa[y] = x;
    pushup(y), pushup(x);
}
void splay(int x)
{
    dfs(x);
    while(!isroot(x))
    {
        int y = fa[x], z = fa[y];
        if(!isroot(y))
            if(son(x) == son(y)) rotate(y);
            else rotate(x);
        rotate(x);
    }
}
inline void access(int x){for(int y = 0;x;y = x, x = fa[x]) splay(x), ch[x][1] = y,pushup(x);}
inline void makeroot(int x){access(x), splay(x), rever(x);}
inline int findroot(int x){access(x), splay(x);while(ch[x][0])x = ch[x][0];splay(x);return x;}
inline void link(int x, int y){makeroot(y), fa[y] = x;}
inline void path(int x, int y){makeroot(x), access(y), splay(y);}
inline void cut(int x, int y){path(x, y);if(ch[y][0] == x) fa[x] = 0, ch[y][0] = 0;pushup(y);}
int n,m,tmp1,tmp2,tmp3;
int main()
{
    read(n), read(m);
    register int i;
    for(i = 1;i + 3 <= n;i += 4)
    {
        read(data[i]), sum[i] = data[i];
        read(data[i + 1]), sum[i + 1] = data[i + 1];
        read(data[i + 2]), sum[i + 2] = data[i + 2];
        read(data[i + 3]), sum[i + 3] = data[i + 3];
    }
    for(;i <= n;++ i) read(data[i]), sum[i] = data[i];
    for(int i = 1;i <= m;++ i)
    {
        read(tmp1), read(tmp2), read(tmp3);
        if(tmp1 == 0) path(tmp2, tmp3), printf("%d\n", sum[tmp3]);
        else if(tmp1 == 1)
        {
            int f1 = findroot(tmp2), f2 = findroot(tmp3);
            if(f1 != f2) link(tmp2, tmp3);
        }
        else if(tmp1 == 2)
        {
            int f1 = findroot(tmp2), f2 = findroot(tmp3);
            if(f1 == f2) cut(tmp2, tmp3);
        }
        else access(tmp2), splay(tmp2), data[tmp2] = tmp3, pushup(tmp2);
    }
    return 0;
}

原文地址:https://www.cnblogs.com/huibixiaoxing/p/8414045.html

时间: 2024-10-25 04:48:13

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\)模板题

bzoj2049-洞穴勘测(动态树lct模板题)

Description 辉辉热衷于洞穴勘测.某天,他按照地图来到了一片被标记为JSZX的洞穴群地区.经过初步勘测,辉辉发现这片区域由n个洞穴(分别编号为1到n)以及若干通道组成,并且每条通道连接了恰好两个洞穴.假如两个洞穴可以通过一条或者多条通道按一定顺序连接起来,那么这两个洞穴就是连通的,按顺序连接在一起的这些通道则被称之为这两个洞穴之间的一条路径.洞穴都十分坚固无法破坏,然而通道不太稳定,时常因为外界影响而发生改变,比如,根据有关仪器的监测结果,123号洞穴和127号洞穴之间有时会出现一条通

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