博客
关于我
强烈建议你试试无所不能的chatGPT,快点击我
BZOJ3282Tree——LCT
阅读量:5783 次
发布时间:2019-06-18

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

题目描述

给定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行,每行三个整数,分别代表操作类型和操作所需的量。
1<=N,M<=300000

输出

对于每一个0号操作,你须输出X到Y的路径上点权的Xor和。

样例输入

3 3
1
2
3
1 1 2
0 1 2
0 1 1

样例输出

3
1
 
LCT模板题,splay维护子树异或和即可。因为cut时不保证边存在,所以注意cut时的判断。
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
using namespace std;int n,m;int x,y;int opt;int v[300010];int f[300010];int s[300010][2];int st[300010];int r[300010];int sum[300010];int get(int rt){ return rt==s[f[rt]][1];}void pushup(int rt){ sum[rt]=v[rt]^sum[s[rt][0]]^sum[s[rt][1]];}void pushdown(int rt){ if(r[rt]) { swap(s[rt][0],s[rt][1]); r[s[rt][0]]^=1; r[s[rt][1]]^=1; r[rt]^=1; }}int is_root(int rt){ return s[f[rt]][0]!=rt&&s[f[rt]][1]!=rt;}void rotate(int rt){ int fa=f[rt]; int anc=f[fa]; int k=get(rt); if(!is_root(fa)) { s[anc][fa==s[anc][1]]=rt; } s[fa][k]=s[rt][k^1]; f[s[fa][k]]=fa; s[rt][k^1]=fa; f[fa]=rt; f[rt]=anc; pushup(fa); pushup(rt);}void splay(int rt){ int top=0; st[++top]=rt; for(int i=rt;!is_root(i);i=f[i]) { st[++top]=f[i]; } for(int i=top;i>=1;i--) { pushdown(st[i]); } for(int fa;!is_root(rt);rotate(rt)) { if(!is_root(fa=f[rt])) { rotate(get(rt)==get(fa)?fa:rt); } }}void access(int rt){ for(int x=0;rt;x=rt,rt=f[rt]) { splay(rt); s[rt][1]=x; pushup(rt); }}void reverse(int rt){ access(rt); splay(rt); r[rt]^=1;}int find(int rt){ access(rt); splay(rt); while(s[rt][0]) { rt=s[rt][0]; } return rt;}void link(int x,int y){ reverse(x); f[x]=y;}void cut(int x,int y){ reverse(x); access(y); splay(y); if(s[x][1]||f[x]!=y||s[y][get(x)^1]) { return ; } s[y][0]=f[x]=0;}void change(int rt,int x){ v[rt]=x; access(rt); splay(rt);}int query(int x,int y){ reverse(x); access(y); splay(y); return sum[y];}int main(){ scanf("%d%d",&n,&m); for(int i=1;i<=n;i++) { scanf("%d",&v[i]); } while(m--) { scanf("%d%d%d",&opt,&x,&y); if(opt==0) { printf("%d\n",query(x,y)); } else if(opt==1&&find(x)!=find(y)) { link(x,y); } else if(opt==2&&find(x)==find(y)) { cut(x,y); } else if(opt==3) { change(x,y); } }}

转载于:https://www.cnblogs.com/Khada-Jhin/p/9744724.html

你可能感兴趣的文章
PAT A1116
查看>>
App上架/更新怕被拒? iOS过审“避雷秘籍”请查收
查看>>
CentOS 7 防火墙操作
查看>>
关于 top 工具的 6 个替代方案
查看>>
程序员最讨厌的9句话,你可有补充?
查看>>
PAT A1037
查看>>
DevOps自动化工具集合
查看>>
淘宝放大镜的两种实现方法JS
查看>>
浅谈RPC
查看>>
绝句二首-杜甫
查看>>
一个有意思的递归定义
查看>>
论文笔记之: Recurrent Models of Visual Attention
查看>>
命令行调用dubbo远程服务
查看>>
discuz 帖子模块用到的表及自动发帖函数
查看>>
如何将finecms链接URL中的list和show去掉
查看>>
SMS短信PDU编码
查看>>
企业级memcached部署(session共享)
查看>>
Eclipse内常用到的一些插件
查看>>
C# 应用程序配置文件操作
查看>>
[原创翻译]Protocol Buffer Basics: C#
查看>>