传送门

处理路径 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);
}
}

最新文章

  1. make menuconfig出错,需要安装libncurses5-dev找不到文件的终极解决办法(不必更换源,适用于ubuntu 32位平台)
  2. jieba中文分词的.NET版本:jieba.NET
  3. [react native] react-native-tab-navigator在子Component中隐藏
  4. pytessact 出现Error2错误
  5. Cas_Java客户端登录相关过滤器的处理流程
  6. HDU5289
  7. setOnClickListener报空指针异常
  8. COM学习(二)——COM的注册和卸载
  9. Chrome浏览器及调试教程
  10. C# Cookie方法
  11. mysql下载和安装
  12. Tomcat 七 HTTP 连接器
  13. TZOJ 二分图练习
  14. [转帖学习]Howto Shrink a Thin Provisioned Virtual Disk (VMDK)
  15. 解题:POI 2004 String
  16. 定时IIS任务自动停止及解决办法
  17. sql 传入参数为逗号分隔的字符串处理方法
  18. 关闭会声会影2018提示UEIP.dll找不到指定模块
  19. python 锁 信号量 事件 队列
  20. C Primer Plus note5

热门文章

  1. JavaScript编程艺术-第7章代码汇总(2)
  2. win10家庭版添加本地账户方法
  3. [C++ STL] list使用详解
  4. 模拟 URAL 1149 Sinus Dances
  5. Java多线程——线程之间的同步
  6. 联想 Vibe Shot(Z90-3) 免recovery 获取ROOT权限 救砖 VIBEUI V3.1_1625
  7. swift Enumerations
  8. 并发编程学习笔记(9)----AQS的共享模式源码分析及CountDownLatch使用及原理
  9. GC策略
  10. Flask框架 之重定向、cookie和session