博客
关于我
强烈建议你试试无所不能的chatGPT,快点击我
BZOJ3282: Tree (LCT模板)
阅读量:4518 次
发布时间:2019-06-08

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

Description

给定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。

Input

第1行两个整数,分别为N和M,代表点数和操作数。
第2行到第N+1行,每行一个整数,整数在[1,10^9]内,代表每个点的权值。
第N+2行到第N+M+1行,每行三个整数,分别代表操作类型和操作所需的量。
1<=N,M<=300000

Output

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

Sample Input

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

Sample Output

3
1

解题思路:

这是LCT很好的模板。
主要难点是处理一下路径权值,和判断两个点是否联通(以防重边)
路径权值:单独将x到y的路径提取(split)Splay维护链的时候在将节点处权值上传,最后查值就好
判断有无x到y的边:将x到y的路径提取,若直接连接无中间值就是有边。
代码:
1 #include
2 #include
3 #include
4 #define lll tr[spc].ch[0] 5 #define rrr tr[spc].ch[1] 6 #define ls ch[0] 7 #define rs ch[1] 8 const int N=200000; 9 struct trnt{ 10 int ch[2]; 11 int lzt; 12 int fa; 13 int val; 14 int sum; 15 bool anc; 16 }tr[N]; 17 int n,m; 18 int cnt; 19 bool whc(int spc) 20 { 21 return tr[tr[spc].fa].rs==spc; 22 } 23 void pushup(int spc) 24 { 25 tr[spc].sum=tr[lll].sum^tr[rrr].sum^tr[spc].val; 26 return ; 27 } 28 void trr(int spc) 29 { 30 if(!spc) 31 return ; 32 std::swap(lll,rrr); 33 tr[spc].lzt^=1; 34 return ; 35 } 36 void pushdown(int spc) 37 { 38 if(tr[spc].lzt) 39 { 40 trr(lll); 41 trr(rrr); 42 tr[spc].lzt=0; 43 } 44 return ; 45 } 46 void recal(int spc) 47 { 48 if(!tr[spc].anc) 49 recal(tr[spc].fa); 50 pushdown(spc); 51 } 52 void rotate(int spc) 53 { 54 int f=tr[spc].fa; 55 bool k=whc(spc); 56 tr[f].ch[k]=tr[spc].ch[!k]; 57 tr[spc].ch[!k]=f; 58 if(tr[f].anc) 59 { 60 tr[f].anc=false; 61 tr[spc].anc=true; 62 }else 63 tr[tr[f].fa].ch[whc(f)]=spc; 64 tr[spc].fa=tr[f].fa; 65 tr[f].fa=spc; 66 tr[tr[f].ch[k]].fa=f; 67 pushup(f); 68 pushup(spc); 69 } 70 void splay(int spc) 71 { 72 recal(spc); 73 while(!tr[spc].anc) 74 { 75 int ft=tr[spc].fa; 76 if(tr[ft].anc) 77 { 78 rotate(spc); 79 return ; 80 } 81 if(whc(spc)^whc(ft)) 82 rotate(spc); 83 else 84 rotate(ft); 85 rotate(spc); 86 } 87 return ; 88 } 89 void access(int spc) 90 { 91 int lsts=0; 92 while(spc) 93 { 94 splay(spc); 95 tr[rrr].anc=true; 96 tr[lsts].anc=false; 97 rrr=lsts; 98 pushup(spc); 99 lsts=spc;100 spc=tr[spc].fa;101 }102 return ;103 }104 void Mtr(int spc)105 {106 107 access(spc);108 splay(spc);109 trr(spc);110 return ;111 }112 int spmrt(int spc)113 {114 access(spc);115 splay(spc);116 while(lll)117 {118 pushdown(spc);119 spc=lll;120 }121 return spc;122 }123 void split(int x,int y)124 {125 Mtr(x);126 access(y);127 splay(y);128 }129 void Link(int x,int y)130 {131 Mtr(x);132 if(spmrt(y)!=x)133 tr[x].fa=y;134 return ;135 }136 void Cut(int x,int y)137 {138 Mtr(x);139 if(spmrt(y)==x&&tr[x].fa==y&&!tr[y].rs)140 {141 tr[x].anc=1;142 tr[y].ls=0;143 tr[x].fa=0;144 pushup(y);145 }146 return ;147 }148 int main()149 {150 scanf("%d%d",&n,&m);151 for(int i=1;i<=n;i++)152 {153 scanf("%d",&tr[i].val);154 tr[i].anc=true;155 }156 while(m--)157 {158 int cmd,x,y;159 scanf("%d%d%d",&cmd,&x,&y);160 if(cmd==0)161 {162 split(x,y);163 printf("%d\n",tr[y].sum);164 }165 if(cmd==1)166 Link(x,y);167 if(cmd==2)168 Cut(x,y);169 if(cmd==3)170 {171 splay(x);172 tr[x].val=y;173 pushup(x);174 }175 }176 return 0;177 }

 

转载于:https://www.cnblogs.com/blog-Dr-J/p/9638970.html

你可能感兴趣的文章
android 按menu键解锁功能的开关
查看>>
wpf 自定义窗口,最大化时覆盖任务栏解决方案
查看>>
Linux 下的dd命令使用详解
查看>>
POJ-1273 Drainage Ditches 最大流Dinic
查看>>
ASP.NET学习记录点滴
查看>>
uva 12097(二分)
查看>>
[Noip2016] 愤怒的小鸟
查看>>
Linux系统基础管理
查看>>
遭遇浏览器兼容性问题,这次是某些浏览器回退功能不正常
查看>>
JAVA wait()和notifyAll()实现线程间通讯
查看>>
python全栈脱产第11天------装饰器
查看>>
koa2 从入门到进阶之路 (一)
查看>>
Java / Android 基于Http的多线程下载的实现
查看>>
求职历程-----我的简历
查看>>
[总结]数据结构(板子)
查看>>
网页图片加载失败,用默认图片替换
查看>>
C# 笔记
查看>>
android 之输入法
查看>>
编译参数-ObjC的说明
查看>>
配置Synergy(Server : XP, client: Win7)
查看>>