[Luogu 3690]【模板】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。
Input
第1行两个整数,分别为N和M,代表点数和操作数。
第2行到第N+1行,每行一个整数,整数在[1,10^9]内,代表每个点的权值。
第N+2行到第N+M+1行,每行三个整数,分别代表操作类型和操作所需的量。
Output
对于每一个0号操作,你须输出X到Y的路径上点权的Xor和。
Sample Input
3 3
1
2
3
1 1 2
0 1 2
0 1 1
Sample Output
3
1
HINT
数据范围: $ 1 \leq N, M \leq 3 \cdot {10}^5 $
题解
维护$xor$和维护子树大小类似。
这道题用到的技巧:
找根:$access(o)$及$splay(o)$后一直往左走。最后一个节点就是根。(理由:由于$LCT$中$splay$的性质:按深度作为键值);
判断是否之间有边:再$cut$之前,判断根的左儿子是否是另外一个点。(理由:若存在边,则包含这条边的$splay$只有两个节点)。
//It is made by Awson on 2017.12.28
#include <map>
#include <set>
#include <cmath>
#include <ctime>
#include <queue>
#include <stack>
#include <vector>
#include <cstdio>
#include <string>
#include <cstdlib>
#include <cstring>
#include <iostream>
#include <algorithm>
#define LL long long
#define LD long double
#define Max(a, b) ((a) > (b) ? (a) : (b))
#define Min(a, b) ((a) < (b) ? (a) : (b))
using namespace std;
const int N = 3e5; struct Link_Cut_Tree {
int ch[N+][], pre[N+], val[N+], xr[N+], isrt[N+], rev[N+];
void pushup(int o) {
if (!o) return;
xr[o] = xr[ch[o][]]^xr[ch[o][]]^val[o];
}
void pushdown(int o) {
if (!o || !rev[o]) return;
int ls = ch[o][], rs = ch[o][];
swap(ch[ls][], ch[ls][]), swap(ch[rs][], ch[rs][]);
rev[ls] ^= , rev[rs] ^= , rev[o] = ;
}
void push(int o) {
if (!isrt[o]) push(pre[o]);
pushdown(o);
}
void rotate(int o, int kind) {
int p = pre[o];
ch[p][!kind] = ch[o][kind], pre[ch[o][kind]] = p;
if (isrt[p]) isrt[o] = , isrt[p] = ;
else ch[pre[p]][ch[pre[p]][] == p] = o;
pre[o] = pre[p];
ch[o][kind] = p, pre[p] = o;
pushup(p), pushup(o);
}
void splay(int o) {
push(o);
while (!isrt[o]) {
if (isrt[pre[o]]) rotate(o, ch[pre[o]][] == o);
else {
int p = pre[o], kind = ch[pre[p]][] == p;
if (ch[p][kind] == o) rotate(o, !kind), rotate(o, kind);
else rotate(p, kind), rotate(o, kind);
}
}
}
void access(int o) {
int y = ;
while (o) {
splay(o);
xr[o] ^= xr[ch[o][]];
isrt[ch[o][]] = , isrt[ch[o][] = y] = ;
pushup(o);
o = pre[y = o];
}
}
void makeroot(int o) {
access(o), splay(o);
rev[o] ^= , swap(ch[o][], ch[o][]);
}
int find(int o) {
access(o), splay(o);
while (ch[o][]) o = ch[o][];
return o;
}
void link(int x, int y) {
int p = find(x), q = find(y);
if (p == q) return;
makeroot(x); pre[x] = y;
}
void cut(int x, int y) {
makeroot(x), access(y), splay(y);
if (ch[y][] != x) return;
xr[y] ^= xr[x], ch[y][] = pre[x] = , isrt[x] = ;
}
int query(int x, int y) {
makeroot(x), access(y), splay(y);
return xr[y];
}
void update(int o, int key) {
makeroot(o); val[o] = key; pushup(o);
}
}T;
int n, m, x, opt, y; void work() {
scanf("%d%d", &n, &m);
for (int i = ; i <= n; i++) {
scanf("%d", &x);
T.val[i] = T.xr[i] = x, T.isrt[i] = ;
}
while (m--) {
scanf("%d%d%d", &opt, &x, &y);
if (opt == ) printf("%d\n", T.query(x, y));
else if (opt == ) T.link(x, y);
else if (opt == ) T.cut(x, y);
else T.update(x, y);
}
}
int main() {
work();
return ;
}
[Luogu 3690]【模板】Link Cut Tree (动态树)的更多相关文章
- 洛谷.3690.[模板]Link Cut Tree(动态树)
题目链接 LCT(良心总结) #include <cstdio> #include <cctype> #include <algorithm> #define gc ...
- LCT总结——概念篇+洛谷P3690[模板]Link Cut Tree(动态树)(LCT,Splay)
为了优化体验(其实是强迫症),蒟蒻把总结拆成了两篇,方便不同学习阶段的Dalao们切换. LCT总结--应用篇戳这里 概念.性质简述 首先介绍一下链剖分的概念(感谢laofu的讲课) 链剖分,是指一类 ...
- Link Cut Tree 动态树 小结
动态树有些类似 树链剖分+并查集 的思想,是用splay维护的 lct的根是动态的,"轻重链"也是动态的,所以并没有真正的轻重链 动态树的操作核心是把你要把 修改/询问/... 等 ...
- LCT(link cut tree) 动态树
模板参考:https://blog.csdn.net/saramanda/article/details/55253627 综合各位大大博客后整理的模板: #include<iostream&g ...
- 洛谷P3690 Link Cut Tree (动态树)
干脆整个LCT模板吧. 缺个链上修改和子树操作,链上修改的话join(u,v)然后把v splay到树根再打个标记就好. 至于子树操作...以后有空的话再学(咕咕咕警告) #include<bi ...
- 洛谷P3690 [模板] Link Cut Tree [LCT]
题目传送门 Link Cut Tree 题目背景 动态树 题目描述 给定n个点以及每个点的权值,要你处理接下来的m个操作.操作有4种.操作从0到3编号.点从1到n编号. 0:后接两个整数(x,y),代 ...
- 模板Link Cut Tree (动态树)
题目描述 给定N个点以及每个点的权值,要你处理接下来的M个操作.操作有4种.操作从0到3编号.点从1到N编号. 0:后接两个整数(x,y),代表询问从x到y的路径上的点的权值的xor和.保证x到y是联 ...
- 【刷题】洛谷 P3690 【模板】Link Cut Tree (动态树)
题目背景 动态树 题目描述 给定n个点以及每个点的权值,要你处理接下来的m个操作.操作有4种.操作从0到3编号.点从1到n编号. 0:后接两个整数(x,y),代表询问从x到y的路径上的点的权值的xor ...
- P3690 【模板】Link Cut Tree (动态树)
P3690 [模板]Link Cut Tree (动态树) 认父不认子的lct 注意:不 要 把 $fa[x]$和$nrt(x)$ 混 在 一 起 ! #include<cstdio> v ...
- LuoguP3690 【模板】Link Cut Tree (动态树) LCT模板
P3690 [模板]Link Cut Tree (动态树) 题目背景 动态树 题目描述 给定n个点以及每个点的权值,要你处理接下来的m个操作.操作有4种.操作从0到3编号.点从1到n编号. 0:后接两 ...
随机推荐
- 通过软引用和弱引用提升JVM内存使用性能的方法(面试时找机会说出,一定能提升成功率)
初学者或初级程序员在面试时如果能证明自己具有分析内存用量和内存调优的能力,这相当有利,因为这是针对5年左右相关经验的高级程序员的要求.而对于高级程序员来说,如果能在面试时让面试官感觉你确实做过内存调优 ...
- TOJ 1214: 数据结构练习题――线性表操作
描述 请你定义一个线性表,可以对表进行"在某个位置之前插入一个元素"."删除某个位置的元素"."清除所有元素"."获取某个位置的元 ...
- 每日冲刺报告——Day3(Java-Team)
第三天报告(11.4 周六) 团队:Java-Team 成员: 章辉宇(284) 吴政楠(286) 陈阳(PM:288) 韩华颂(142) 胡志权(143) github地址:https://git ...
- 第201621123043 《Java程序设计》第12周学习总结
1. 本周学习总结 1.1 以你喜欢的方式(思维导图或其他)归纳总结多流与文件相关内容. 2. 面向系统综合设计-图书馆管理系统或购物车 使用流与文件改造你的图书馆管理系统或购物车. 2.1 简述如何 ...
- Java 后端微信小程序支付demo (网上说的坑里面基本上都有)
Java 后端微信小程序支付 一.遇到的问题 1. 商户号该产品权限未开通,请前往商户平台>产品中心检查后重试 2.签名错误 3.已经调起微信统一下单接口,可以拿到预支付ID,但是前端支付的时候 ...
- Java可重入锁如何避免死锁
本文由https://bbs.csdn.net/topics/390939500和https://zhidao.baidu.com/question/1946051090515119908.html启 ...
- LeetCode & Q88-Merge Sorted Array-Easy
Array Two Pointers Description: Given two sorted integer arrays nums1 and nums2, merge nums2 into nu ...
- 微信小程序tab(swiper)切换
<- wxml -> <view class="youhui"> <view ' bindtap='toggle'> 未使用 </view ...
- api-gateway实践(15)3.6JL分支和3.7并行改造需求
一.名称改为"API网关" --哪个地方的名称?二.开发者视图中,API网关显示两个视图. 1. 服务分类视图:支持按照业务分为多个类别,分类方式参照应用服务化的分类:人像比对.自 ...
- 图数据库orientDB(1-1)SQL基本操作
SQL基本操作 1.新增VerTex CREATE VERTEX V SET name="user01",sex="M",age="25"; ...