[luoguP3690] 【模板】Link Cut Tree
2024-08-28 09:49:33
处理路径 xor 和的时候可以维护子树 xor 和,先提取出路径,再把一个点 splay 到最上方,直接取子树 xor 和即可。
更新一个点权时可以先提取出根到这个点的路径,把这个点 splay 到最上方,然后 update 即可。
——代码
#include <cstdio>
#include <iostream>
#define N 300001
#define get(x) (son[f[x]][1] == (x))
#define swap(x, y) ((x) ^= (y) ^= (x) ^= (y))
#define isroot(x) (son[f[x]][0] ^ (x) && son[f[x]][1] ^ (x)) int n, m;
int a[N], sum[N], son[N][], rev[N], f[N], s[N]; inline int read()
{
int x = , f = ;
char ch = getchar();
for(; !isdigit(ch); ch = getchar()) if(ch == '-') f = -;
for(; isdigit(ch); ch = getchar()) x = (x << ) + (x << ) + ch - '';
return x * f;
} inline void update(int x)
{
if(x)
{
sum[x] = a[x];
if(son[x][]) sum[x] ^= sum[son[x][]];
if(son[x][]) sum[x] ^= sum[son[x][]];
}
} inline void pushdown(int x)
{
if(x && rev[x])
{
swap(son[x][], son[x][]);
if(son[x][]) rev[son[x][]] ^= ;
if(son[x][]) rev[son[x][]] ^= ;
rev[x] = ;
}
} inline void rotate(int x)
{
int old = f[x], oldf = f[old], wh = get(x); if(!isroot(old))
son[oldf][get(old)] = x;
f[x] = oldf; son[old][wh] = son[x][wh ^ ];
f[son[old][wh]] = old; son[x][wh ^ ] = old;
f[old] = x; update(old);
update(x);
} inline void splay(int x)
{
int i, fa, t = ;
s[++t] = x;
for(i = x; !isroot(i); i = f[i]) s[++t] = f[i];
for(i = t; i >= ; i--) pushdown(s[i]);
for(; !isroot(x); rotate(x))
if(!isroot(fa = f[x]))
rotate(get(x) ^ get(fa) ? x : fa);
} inline void access(int x)
{
for(int t = ; x; t = x, x = f[x]) splay(x), son[x][] = t, update(x);
} inline void reverse(int x)
{
access(x);
splay(x);
rev[x] ^= ;
} inline int query(int x, int y)
{
reverse(x);
access(y);
splay(y);
return sum[y];
} inline int find(int x)
{
access(x);
splay(x);
while(son[x][]) x = son[x][];
return x;
} inline void link(int x, int y)
{
reverse(x);
f[x] = y;
access(x);
} inline void cut(int x, int y)
{
reverse(x);
access(y);
splay(y);
son[y][] = f[x] = ;
update(y);
} inline void change(int x, int y)
{
access(x);
splay(x);
a[x] = y;
update(x);
} int main()
{
int i, x, y, z;
n = read();
m = read();
for(i = ; i <= n; i++) a[i] = read();
for(i = ; i <= m; i++)
{
z = read();
x = read();
y = read();
if(z == ) printf("%d\n", query(x, y));
if(z == )
if(find(x) ^ find(y))
link(x, y);
if(z == )
if(find(x) == find(y))
cut(x, y);
if(z == ) change(x, y);
}
}
最新文章
- make menuconfig出错,需要安装libncurses5-dev找不到文件的终极解决办法(不必更换源,适用于ubuntu 32位平台)
- jieba中文分词的.NET版本:jieba.NET
- [react native] react-native-tab-navigator在子Component中隐藏
- pytessact 出现Error2错误
- Cas_Java客户端登录相关过滤器的处理流程
- HDU5289
- setOnClickListener报空指针异常
- COM学习(二)——COM的注册和卸载
- Chrome浏览器及调试教程
- C# Cookie方法
- mysql下载和安装
- Tomcat 七 HTTP 连接器
- TZOJ 二分图练习
- [转帖学习]Howto Shrink a Thin Provisioned Virtual Disk (VMDK)
- 解题:POI 2004 String
- 定时IIS任务自动停止及解决办法
- sql 传入参数为逗号分隔的字符串处理方法
- 关闭会声会影2018提示UEIP.dll找不到指定模块
- python 锁 信号量 事件 队列
- C Primer Plus note5
热门文章
- JavaScript编程艺术-第7章代码汇总(2)
- win10家庭版添加本地账户方法
- [C++ STL] list使用详解
- 模拟 URAL 1149 Sinus Dances
- Java多线程——线程之间的同步
- 联想 Vibe Shot(Z90-3) 免recovery 获取ROOT权限 救砖 VIBEUI V3.1_1625
- swift Enumerations
- 并发编程学习笔记(9)----AQS的共享模式源码分析及CountDownLatch使用及原理
- GC策略
- Flask框架 之重定向、cookie和session