BZOJ3282: Tree (LCT模板)
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
1
2
3
1 1 2
0 1 2
0 1 1
Sample Output
3
1
1
解题思路:
这是LCT很好的模板。
主要难点是处理一下路径权值,和判断两个点是否联通(以防重边)
路径权值:单独将x到y的路径提取(split)Splay维护链的时候在将节点处权值上传,最后查值就好
判断有无x到y的边:将x到y的路径提取,若直接连接无中间值就是有边。
代码:
1 #include<cstdio> 2 #include<cstring> 3 #include<algorithm> 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 }