题目背景

动态树

题目描述

给定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, M \leq 3 \cdot {10}^51≤N,M≤3⋅105

看了一下午的讲解

看了一晚上的代码

算是差不多理解了,不过还有一个潜在的隐患没有解决,就是代码里那个玄学的pushdown函数

等搞懂了再整理吧

// luogu-judger-enable-o2
// luogu-judger-enable-o2
// luogu-judger-enable-o2
#include<cstdio>
#include<cstring>
#include<algorithm>
using namespace std;
const int MAXN= * 1e5 + ;
inline int read()
{
char c = getchar();int x = ,f = ;
while(c < '' || c > ''){if(c == '-')f = -;c = getchar();}
while(c >= '' && c <= ''){x = x * + c - '',c = getchar();}
return x * f;
}
#define fa(x) T[x].f
#define ls(x) T[x].ch[0]
#define rs(x) T[x].ch[1]
int v[MAXN];
struct node {
int f, ch[], s;
bool r;
}T[MAXN];
int ident(int x) {
return T[fa(x)].ch[] == x ? : ;//判断该节点是父亲的哪个儿子
}
int connect(int x,int fa,int how) {
T[x].f=fa;
T[fa].ch[how]=x;//连接
}
inline bool IsRoot(int x) {//若为splay中的根则返回1 否则返回0
return ls( fa(x) ) != x && rs( fa(x) ) != x;
//用到了两个性质
//1.若x与fa(x)之间的边是虚边,那么它的父亲的孩子中不会有他(不在同一个splay内)
//2. splay的根节点与其父亲之间的边是虚边
}
void update(int x) {
T[x].s = T[ls(x)].s ^ T[rs(x)].s ^ v[x];//维护路径上的异或和
}
void pushdown(int x) {
if(T[x].r) {
swap(ls(x),rs(x));
T[ls(x)].r ^= ;
T[rs(x)].r ^= ;
T[x].r = ;//标记下传
}
}
void rotate(int x) {
int Y = T[x].f, R = T[Y].f, Yson = ident(x), Rson = ident(Y);
int B = T[x].ch[Yson ^ ];
//Q为什么要这样写 ******************************************** T[x].f = R;
if(!IsRoot(Y))
connect(x, R, Rson);
//这里如果不判断y是否根节点,那么当y是根节点的时候,0节点的儿子就会被更新为x
//这样x就永远不能被判断为根节点,也就会无限循环下去了
//但是这里不更新x的父亲的话就会出现无限递归的情况
connect(B, Y, Yson);
connect(Y, x, Yson ^ );
update(Y); update(x);
}
int st[MAXN];
void splay(int x) {
int y = x, top = ;
st[++top] = y;
while(!IsRoot(y)) st[++top] = y = fa(y);
while(top) pushdown(st[top--]);
//因为在旋转的时候不会处理标记,所以splay之前应该下传所有标记
for(int y = fa(x); !IsRoot(x); rotate(x), y = fa(x))//只要不是根就转
if(!IsRoot(y))
rotate( ident(x) == ident(y) ? x : y );
}
void access(int x) {//访问x节点
for(int y = ; x; x = fa(y = x))
splay(x), rs(x) = y, update(x);
//首先把x splay到所在平衡树的根,这样可以保证它的右孩子就是在原树中对应的重链(右孩子深度比它大)
//y是splay中x的儿子,把x的右儿子改成y,也就是把x和y之间的边变成实边
//更改了节点顺序,需要update
}
void makeroot(int x) {//把x改为原树的根节点
access(x);
splay(x);
T[x].r ^= ;
pushdown(x);
//首先访问一下x,再把x转到根,
//注意在access的时候都是连接的右儿子,这样会破坏顺序,因此我们需要将左右儿子翻转
}
int findroot(int x) {//找到x在原树中的根节点
access(x);splay(x);
while(ls(x)) x = ls(x);//找到深度最小的点即为根节点
return x;
}
void split(int x, int y) {
makeroot(x);//首先把x置为根节点
access(y); splay(y);
//然后访问一下y,再把y转到根节点,这样y维护的就是x - y 路径上的xor
}
void link(int x, int y) {
makeroot(x);//把x置为根节点
if(findroot(y) != x ) fa(x) = y;
//如果x与y不在同一个splay中,就把y置为x的父亲
//因为不能判断x与y的深度,因此在这里不用更新y的儿子
}
void cut(int x, int y) {
makeroot(x);
if(findroot(y) == x && fa(x) == y && !rs(x)) {
fa(x) = T[y].ch[] = ;
update(y);
}
//注意findroot(y)之后,y会成为根节点
//对于第三个判断
//可以构造出这样的树
// x
// fuck
// y
//在splay中是这样的
// y
//x
// fuck
//这样很显然x与y是不相连的
}
int main()
{
#ifdef WIN32
freopen("a.in","r",stdin);
//freopen("a.out","w",stdout);
#else
#endif
int N = read(), M = read();
for(int i = ; i <= N; i++) v[i] = read();
for(int i = ; i <= M; i++) {
int opt = read(), x = read(), y = read();
if(opt == ) split(x, y), printf("%d\n",T[y].s);
else if(opt == ) link(x, y);
else if(opt == ) cut(x, y);
else if(opt == ) splay(x), v[x] = y;
}
return ;
}

洛谷P3690 【模板】Link Cut Tree (LCT)的更多相关文章

  1. 洛谷P3690 [模板] Link Cut Tree [LCT]

    题目传送门 Link Cut Tree 题目背景 动态树 题目描述 给定n个点以及每个点的权值,要你处理接下来的m个操作.操作有4种.操作从0到3编号.点从1到n编号. 0:后接两个整数(x,y),代 ...

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

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

  3. 洛谷.3690.[模板]Link Cut Tree(动态树)

    题目链接 LCT(良心总结) #include <cstdio> #include <cctype> #include <algorithm> #define gc ...

  4. BZOJ 3282 Link Cut Tree (LCT)

    题目大意:维护一个森林,支持边的断,连,修改某个点的权值,求树链所有点点权的异或和 洛谷P3690传送门 搞了一个下午终于明白了LCT的原理 #include <cstdio> #incl ...

  5. 模板Link Cut Tree (动态树)

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

  6. 【刷题】洛谷 P3690 【模板】Link Cut Tree (动态树)

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

  7. Luogu 3690 Link Cut Tree

    Luogu 3690 Link Cut Tree \(LCT\) 模板题.可以参考讲解和这份码风(个人认为)良好的代码. 注意用 \(set\) 来维护实际图中两点是否有直接连边,否则无脑 \(Lin ...

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

    [模板]Link Cut Tree 思路: LCT模板: 代码: #include <bits/stdc++.h> using namespace std; #define maxn 30 ...

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

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

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

    P3690 [模板]Link Cut Tree (动态树) 题目背景 动态树 题目描述 给定n个点以及每个点的权值,要你处理接下来的m个操作.操作有4种.操作从0到3编号.点从1到n编号. 0:后接两 ...

随机推荐

  1. MySQL数据库(7)----数据库的选择、创建、删除和更改

    1.选择数据库 使用 USE 语句可以选择数据库,并把它指定为MySQL服务器连接的默认(当前)数据库: USE db_name; 要想选择数据库,用户必须要具备相应的访问权限:否则,会出现错误提示. ...

  2. Setting up a Single Node Cluster Hadoop on Ubuntu/Debian

    Hadoop: Setting up a Single Node Cluster. Hadoop: Setting up a Single Node Cluster. Purpose Prerequi ...

  3. 【Yii系列】错误处理和日志系统

    缘起 跟随上一章的脚步,上一章中,我们主要讲解了在用户发起请求,解析请求,服务器反馈请求以及session的一些知识点,这过程中,难免会遇到一些问题,比方说数据库查询失败,用户输入导致脚本出错,网络问 ...

  4. git命令图

  5. Java BigDecimal初探

    更新时间:2016-03-17 一.引言 <Effactive Java>中有这样的描述:float和double类型的主要设计目标是为了科学计算和工程计算.他们执行二进制浮点运算,这是为 ...

  6. 转 string和byte[]的转换 (C#)

    转 string和byte[]的转换 (C#)  string类型转成byte[]: byte[] byteArray = System.Text.Encoding.Default.GetBytes ...

  7. spider-抓取网页内容

    使用urllib2抓取网页内容: import urllib2 from HTMLParser import HTMLParser request = urllib2.Request('http:// ...

  8. Compare DML To Both REDO And UNDO Size

    SUMMARY you can remember undo rule  the same to redo if you want demo rule that you can look up the ...

  9. 英语的各种 n. adj. vt. vi. 等词性解释

    n. 名词 v. 动词(既可作及物动词,也可作不及物动词的就用这个表示) pron. 代词 adj. 形容词(后接名词) adv. 副词(修饰动词.形容词或其他副词) abbr. (这是一个缩写符号) ...

  10. CSS 预处理器

    在程序员眼里,css不像其他程序语言(例如PHP, Javascript等等),有自己的变量.常量.条件语句以及一些编程语法,它只是一行行单纯的属性描述,写起来相当费事,而且代码难以组织和维护.自然的 ...