「Luogu P3690」【模板】Link Cut Tree (动态树) 发表于 2018-12-22 | 字数统计: 652 | 阅读时长 ≈ 3 给定$n$个点以及它们的点权,要求写一种数据结构支持以下操作:求$x$到$y$路径上点权的$operatorname{xor}$和,连接或删除一条边,以及修改某个点的点权。 链接题解一道LCT裸题。坑。 代码123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173#include<bits/stdc++.h>using namespace std;typedef int ll;const ll MAXN=3e5+51;ll cnt,qcnt,op,x,y;ll num[MAXN];inline ll read(){ register ll num=0,neg=1; register char ch=getchar(); while(!isdigit(ch)&&ch!='-') { ch=getchar(); } if(ch=='-') { neg=-1; ch=getchar(); } while(isdigit(ch)) { num=(num<<3)+(num<<1)+(ch-'0'); ch=getchar(); } return num*neg;}namespace LCT{ struct Node{ ll fa,val,tag; ll ch[2]; }; struct LinkCutTree{ Node nd[MAXN]; ll st[MAXN]; inline bool nroot(ll x) { return nd[nd[x].fa].ch[0]==x||nd[nd[x].fa].ch[1]==x; } inline void update(ll x) { nd[x].val=nd[nd[x].ch[0]].val^nd[nd[x].ch[1]].val^num[x]; } inline void reverse(ll x) { swap(nd[x].ch[0],nd[x].ch[1]),nd[x].tag^=1; } inline void spread(ll x) { if(nd[x].tag) { if(nd[x].ch[0]) { reverse(nd[x].ch[0]); } if(nd[x].ch[1]) { reverse(nd[x].ch[1]); } nd[x].tag=0; } } inline void rotate(ll x) { ll fa=nd[x].fa,gfa=nd[fa].fa; ll dir=nd[fa].ch[1]==x,son=nd[x].ch[!dir]; if(nroot(fa)) { nd[gfa].ch[nd[gfa].ch[1]==fa]=x; } nd[x].ch[!dir]=fa,nd[fa].ch[dir]=son; if(son) { nd[son].fa=fa; } nd[fa].fa=x,nd[x].fa=gfa; update(fa); } inline void splay(ll x) { ll fa=x,gfa,cur=0; st[++cur]=fa; while(nroot(fa)) { st[++cur]=fa=nd[fa].fa; } while(cur) { spread(st[cur--]); } while(nroot(x)) { fa=nd[x].fa,gfa=nd[fa].fa; if(nroot(fa)) { rotate((nd[fa].ch[0]==x)^(nd[gfa].ch[0]==fa)?x:fa); } rotate(x); } update(x); } inline void access(ll x) { for(register int i=0;x;x=nd[i=x].fa) { splay(x),nd[x].ch[1]=i,update(x); } } inline void makeRoot(ll x) { access(x),splay(x),reverse(x); } inline ll findRoot(ll x) { access(x),splay(x); while(nd[x].ch[0]) { spread(x),x=nd[x].ch[0]; } return x; } inline void split(ll x,ll y) { makeRoot(x),access(y),splay(y); } inline void link(ll x,ll y) { makeRoot(x); if(findRoot(y)!=x) { nd[x].fa=y; } } inline void cut(ll x,ll y) { makeRoot(x); if(findRoot(y)==x&&nd[x].fa==y&&!nd[x].ch[1]) { nd[x].fa=nd[y].ch[0]=0; update(y); } } };}LCT::LinkCutTree lct;int main(){ cnt=read(),qcnt=read(); for(register int i=1;i<=cnt;i++) { num[i]=read(); } for(register int i=0;i<qcnt;i++) { op=read(),x=read(),y=read(); if(!op) { lct.split(x,y); printf("%d\n",lct.nd[y].val); } if(op==1) { lct.link(x,y); } if(op==2) { lct.cut(x,y); } if(op==3) { lct.splay(x),num[x]=y; } }} 本文作者: Karry5307 本文链接: http://karry5307.github.io/2018/12/22/「Luogu-P3690」【模板】Link-Cut-Tree-(动态树)/ 版权声明: 本博客所有文章除特别声明外,均采用 CC BY-NC-SA 4.0 许可协议。转载请注明出处!