1. 程式人生 > >luogu3690 【模板】Link Cut Tree (動態樹)

luogu3690 【模板】Link Cut Tree (動態樹)

pre class HR name print () OS 模板 pushd

參考there和there

#include <iostream>
#include <cstdio>
using namespace std;
int n, m, val[300005], ch[300005][2], sum[300005], fa[300005], uu, vv, opt;
int rev[300005];
void pushDown(int x){
    if(rev[x]){
        swap(ch[x][0], ch[x][1]);
        rev[ch[x][0]] ^= 1;
        rev[ch[x][1]] ^= 1;
        rev[x] = 0
; } } bool isRoot(int x){ return ch[fa[x]][0]!=x && ch[fa[x]][1]!=x; } void xf(int x){ if(!isRoot(x)) xf(fa[x]); pushDown(x); } bool getW(int x){ return ch[fa[x]][1]==x; } void upd(int x){ sum[x] = sum[ch[x][0]] ^ sum[ch[x][1]] ^ val[x]; } void rotate(int x){ int old=fa[x], oldf=fa[old], w=getW(x); if
(!isRoot(old)) ch[oldf][ch[oldf][1]==old] = x; ch[old][w] = ch[x][w^1]; ch[x][w^1] = old; fa[ch[x][w^1]] = x; fa[ch[old][w]] = old; fa[x] = oldf; upd(old); upd(x); } void splay(int x){ xf(x); while(!isRoot(x)){ int f=fa[x]; if(!isRoot(f)) rotate(getW(x)==getW(f)?f:x); rotate(x); } } void
access(int x){ int y=0; while(x){ splay(x); ch[x][1] = y; upd(x); y = x; x = fa[x]; } } void makeRoot(int x){ access(x); splay(x); rev[x] ^= 1; } int query(int u, int v){ makeRoot(u); access(v); splay(v); return sum[v]; } int findRoot(int x){ access(x); splay(x); while(ch[x][0]) x = ch[x][0]; splay(x);//謎之降低常數 return x; } void link(int u, int v){ makeRoot(u); fa[u] = v; } void cut(int u, int v){ makeRoot(u); access(v); splay(v); if(ch[u][0] || ch[u][1] || fa[u]!=v || ch[v][getW(u)^1]) return ; ch[v][0] = fa[u] = 0; } void change(int u, int v){ val[u] = v; access(u); splay(u); } int main(){ cin>>n>>m; for(int i=1; i<=n; i++) scanf("%d", &val[i]); while(m--){ scanf("%d %d %d", &opt, &uu, &vv); if(opt==0) printf("%d\n", query(uu, vv)); else if(opt==1 && findRoot(uu)!=findRoot(vv)) link(uu, vv); else if(opt==2 && findRoot(uu)==findRoot(vv)) cut(uu, vv); else if(opt==3) change(uu, vv); } return 0; }

luogu3690 【模板】Link Cut Tree (動態樹)