博客
关于我
强烈建议你试试无所不能的chatGPT,快点击我
LuoguP3690 【模板】Link Cut Tree (动态树) LCT模板
阅读量:4982 次
发布时间:2019-06-12

本文共 3234 字,大约阅读时间需要 10 分钟。

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 
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#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
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

你可能感兴趣的文章
闭包 装饰器 - 总结
查看>>
中间件
查看>>
jQuery初识之选择器、样式操作和筛选器(模态框和菜单示例)
查看>>
::作用域运算符
查看>>
memcpy memmove区别和实现
查看>>
linux 下创建并动态加载.so 文件
查看>>
python--redis
查看>>
禁用input帐号密码的自动填充
查看>>
python的小技巧
查看>>
json数组转数组对象
查看>>
KMP算法详解 转帖
查看>>
Struts2+Hibernate+Spring+Webservice 项目从Tomcat到WebLogic遇到问题的解决方法
查看>>
C# 代理/委托 Delegate
查看>>
笨方法学python--参数,解包,变量
查看>>
android 加载本地图片与网络图片
查看>>
易经读书笔记17 泽雷随
查看>>
oracle正则表达式函数 匹配
查看>>
jmeter --自动化badboy脚本开发技术
查看>>
Linux驱动:LCD驱动测试
查看>>
Mark Down 尝试
查看>>