题目大意:给定$n$个点以及每个点的权值,要你处理接下来的$m$个操作。操作有$4$种。操作从$0到3编号。点从1到n编号。

  1. $0,x,y$:代表询问从$x$到$y$的路径上的点的权值的$xor$和。保证$x$到$y$是联通的。
  2. $1,x,y$:代表连接$x$到$y$,若$x$到$y$已经联通则无需连接。
  3. $2,x,y$:代表删除边$(x,y)$,不保证边$(x,y)$存在。
  4. $3,x,y$:代表将点$x$上的权值变成$y$。

题解:$LCT$

卡点:

C++ Code:

#include <cstdio>
#define maxn 300010
#define lc(rt) son[rt][0]
#define rc(rt) son[rt][1]
using namespace std;
int n, m;
int V[maxn], s[maxn];
int son[maxn][2], tg[maxn], fa[maxn];
inline void swap(int &a, int &b) {a ^= b ^= a ^= b;}
inline void swap(int rt) {swap(lc(rt), rc(rt));}
inline int get(int rt, int flag = 1) {return son[fa[rt]][flag] == rt;}
inline bool is_root(int rt) {return !(get(rt, 0) || get(rt));}
inline void pushdown(int rt) {
swap(rt);
tg[lc(rt)] ^= 1, tg[rc(rt)] ^= 1, tg[rt] ^= 1;
}
inline void update(int rt) {s[rt] = s[lc(rt)] ^ s[rc(rt)] ^ V[rt];}
inline void rotate(int x) {
int y = fa[x], z = fa[y], b = get(x);
if (!is_root(y)) son[z][get(y)] = x;
fa[son[y][b] = son[x][!b]] = y; son[x][!b] = y;
fa[y] = x; fa[x] = z;
update(y); update(x);
}
int stack[maxn], top;
inline void splay(int x) {
stack[top = 1] = x;
for (int y = x; !is_root(y); stack[++top] = y = fa[y]);
for (; top; top--) if (tg[stack[top]]) pushdown(stack[top]);
for (; !is_root(x); rotate(x)) if (!is_root(fa[x]))
get(x) ^ get(fa[x]) ? rotate(x) : rotate(fa[x]);
update(x);
}
inline void access(int rt) {for (int t = 0; rt; rc(rt) = t, t = rt, rt = fa[rt]) splay(rt);}
inline void make_root(int rt) {access(rt), splay(rt), tg[rt] ^= 1;}
inline void link(int x, int y) {make_root(x); fa[x] = y;}
inline void cut(int x, int y) {make_root(x); access(y); splay(y); fa[x] = lc(y) = 0;}
inline bool connect(int x, int y) {
make_root(x); access(y); splay(y);
return fa[x] == y;
}
inline bool uni(int x, int y) {
make_root(x); access(y); splay(y);
int tmp = x;
while (tmp) tmp = fa[tmp];
return tmp == y;
}
int main() {
scanf("%d%d", &n, &m);
for (int i = 1; i <= n; i++) {
scanf("%d", &V[i]);
s[i] = V[i];
}
while (m --> 0) {
int op, x, y;
scanf("%d%d%d", &op, &x, &y);
if (op == 0) {
make_root(x); access(y); splay(y);
printf("%d\n", s[y]);
}
if (op == 1) if (!uni(x, y)) link(x, y);
if (op == 2) if (connect(x, y)) cut(x, y);
if (op == 3) {
access(x); splay(x);
V[x] = y;
update(x);
}
}
return 0;
}

最新文章

  1. Quartz.net开源作业调度框架使用详解
  2. javascript的一些知识
  3. Java EE 和 Java Web
  4. 帝国cms7.0设置标题图片(缺失状态下)
  5. ecshop json类的使用
  6. C#中从元数据
  7. Android Studio创建库项目及引用
  8. Bash中的数学计算
  9. mongodb 在windows下面进行分片
  10. STM32的内存管理
  11. dubbo入门学习 四 注册中心 zookeeper入门
  12. JS中将变量转为字符串
  13. elaticsear no [query] registered for [filtered] 错误
  14. Linux学习之挂载光盘和U盘(六)
  15. MXNET:监督学习
  16. 求1+2+……+n的和
  17. CentOS 7.0安装配置Vsftp服务器步骤详解
  18. attenuation
  19. [Android Pro] 终极组件化框架项目方案详解
  20. out.print()与out.write()的区别

热门文章

  1. 介绍几个PHP 自带的加密解密函数
  2. python系列7进程线程和协程
  3. SQL Server中2008及以上 ldf 文件过大的解决方法
  4. 4 echo服务器
  5. Unity3d创建物体,寻找物体,加载物体,添加脚本
  6. Anytime项目开发记录3
  7. Nullable可空类型
  8. vi/vim 命令使用详解
  9. C++学习009预处理器指令符号 # ## #@ 符号的使用
  10. PL/SQL查看表结构