boolisroot(int x){return x != tr[tr[x].fa].s[0] && x != tr[tr[x].fa].s[1];}
inlinevoidrotate(int x) { int y = tr[x].fa, z = tr[y].fa; int k = tr[y].s[1] == x; if (!isroot(y)) tr[z].s[y == tr[z].s[1]] = x; tr[x].fa = z; tr[y].s[k] = tr[x].s[k ^ 1], tr[tr[x].s[k ^ 1]].fa = y; tr[y].fa = x, tr[x].s[k ^ 1] = y; pushup(y), pushup(x); }
inlinevoidupdate(int x) { if (!isroot(x)) update(tr[x].fa); pushdown(x); }
inlinevoidsplay(int x) { update(x);//先翻转回来 while (!isroot(x)) { int y = tr[x].fa, z = tr[y].fa; if (!isroot(y)) { if ((x == tr[y].s[1]) ^ (y == tr[z].s[1])) rotate(x); elserotate(y); } rotate(x); } }
voidaccess(int x) { int z = x; for (int y = 0; x; y = x, x = tr[y].fa)//最开始的 y 是 0,表示 x 开始没有向儿子的实边了 { splay(x); tr[x].s[1] = y, pushup(x);//更改了信息就要 pushup } splay(z); }
voidmakeroot(int x) { access(x), reverse(x); }
intfindroot(int x) { access(x); while (tr[x].s[0]) pushdown(x), x = tr[x].s[0];//注意要 pushup splay(x); return x; }
voidlink(int x, int y) { makeroot(x); if (findroot(y) != x) tr[x].fa = y; }
voidcut(int x, int y) { makeroot(x); if (findroot(y) == x && tr[y].fa == x && !tr[y].s[0]) { tr[x].s[1] = tr[y].fa = 0; pushup(x); } }
intmain() { cin >> n >> m; for (int i = 1; i <= n; ++ i) scanf("%d", &a[i]); for (int i = 1; i <= n; ++ i) tr[i].val = a[i]; int op, x, y; while (m --) { scanf("%d %d %d", &op, &x, &y); if (op == 0) { makeroot(x), access(y); printf("%d\n", tr[y].val); } elseif (op == 1) link(x, y); elseif (op == 2) cut(x, y); elseif (op == 3){ access(x); a[x] = y, pushup(x); } } return0; }
voidpushdown(int x) { if (!tr[x].flag) return; reverse(tr[x].s[0]);reverse(tr[x].s[1]); tr[x].flag=0; }
voidrotate(int x) { int y=tr[x].p,z=tr[y].p; int k=tr[y].s[1]==x; if (!isroot(y)) tr[z].s[tr[z].s[1]==y]=x; tr[x].p=z; tr[y].s[k]=tr[x].s[k^1],tr[tr[x].s[k^1]].p=y; tr[x].s[k^1]=y,tr[y].p=x; pushup(y);pushup(x); }
voidupdata(int x) { if (!isroot(x)) updata(tr[x].p); pushdown(x); }
voidsplay(int x) { updata(x); while (!isroot(x)) { int y=tr[x].p,z=tr[y].p; if (!isroot(y)) if ((tr[z].s[1]==y)^(tr[y].s[1]==x)) rotate(x); elserotate(y); rotate(x); } }
voidaccess(int x) { int z=x; for (int y=0;x;y=x,x=tr[y].p) { splay(x); tr[x].s[1]=y;pushup(x); } splay(z); }