【模板】LCT
P3690 【模板】动态树(LCT)
#include <algorithm>
#include <cstdio>
#include <cstring>
using namespace std;
typedef long long LL;
template <int N>
struct lctree {
int val[N + 10], sum[N + 10], fa[N + 10], ch[N + 10][2], rev[N + 10];
bool getson(int p) { return ch[fa[p]][1] == p; }
bool isroot(int p) { return !p || ch[fa[p]][getson(p)] != p; }
void maintain(int p) { sum[p] = val[p] ^ sum[ch[p][0]] ^ sum[ch[p][1]]; }
void pushdown(int p) {
if (rev[p])
swap(ch[p][0], ch[p][1]), rev[ch[p][0]] ^= 1, rev[ch[p][1]] ^= 1,
rev[p] ^= 1;
}
void update(int p) {
if (!isroot(p)) update(fa[p]);
pushdown(p);
}
void connect(int p, int q, int r) { fa[p] = q, ch[q][r] = p; } // p->q
void rotate(int p) {
int f = fa[p], r = getson(p);
if (fa[p] = fa[f], !isroot(f)) connect(p, fa[f], getson(f));
connect(ch[p][r ^ 1], f, r), connect(f, p, r ^ 1), maintain(f), maintain(p);
}
void splay(int p) {
for (update(p); !isroot(p); rotate(p))
if (!isroot(fa[p])) rotate(getson(p) == getson(fa[p]) ? fa[p] : p);
}
int access(int p) {
int y = 0;
for (; p; p = fa[y = p]) splay(p), ch[p][1] = y, maintain(p);
return y;
}
void makeroot(int p) { access(p), splay(p), rev[p] ^= 1; }
int findroot(int p) {
access(p), splay(p);
while (ch[p][0]) p = ch[p][0];
return p;
}
void split(int x, int y) { makeroot(x), access(y), splay(y); }
void link(int x, int y) { makeroot(x), fa[x] = y; }
void cut(int x, int y) {
split(x, y);
if (fa[x] == y && !ch[x][1]) fa[x] = ch[y][0] = 0;
maintain(y);
}
void modify(int x, int y) { splay(x), val[x] = y, maintain(x); }
int lca(int x, int y) { return access(x), access(y); }
};
int n, m;
lctree<100010> t;
int main() {
// #ifdef LOCAL
// freopen("input.in","r",stdin);
// #endif
scanf("%d%d", &n, &m);
for (int i = 1; i <= n; i++) scanf("%d", &t.val[i]), t.sum[i] = t.val[i];
for (int i = 1, op, x, y; i <= m; i++) {
scanf("%d%d%d", &op, &x, &y);
switch (op) {
case 0:
t.split(x, y), printf("%d\n", t.sum[y]);
break;
case 1:
if (t.findroot(x) != t.findroot(y)) t.link(x, y);
break;
case 2:
if (t.findroot(x) == t.findroot(y)) t.cut(x, y);
break;
case 3:
t.modify(x, y);
}
}
return 0;
}
P4219 [BJOI2014] 大融合
template <int N>
struct LCT {
int ch[N + 10][2], fa[N + 10];
bool rev[N + 10];
int sizl[N + 10], siz[N + 10];
bool getson(int p) { return ch[fa[p]][1] == p; }
bool nroot(int p) { return p && ch[fa[p]][getson(p)] == p; }
void maintain(int p) {
if (p) siz[p] = siz[ch[p][0]] + 1 + sizl[p] + siz[ch[p][1]];
}
// siz[p] 有效,当且仅当 p 被 makeroot 了
void reverse(int p) {
swap(ch[p][0], ch[p][1]);
rev[p] ^= 1;
}
void pushdown(int p) {
if (rev[p]) {
reverse(ch[p][0]);
reverse(ch[p][1]);
rev[p] = false;
}
}
void pushall(int p) {
if (nroot(p)) pushall(fa[p]);
pushdown(p);
}
void rotate(int p) {
const auto link = [&](int p, int q, int r) {
fa[p] = q, ch[q][r] = p;
};
int f = fa[p], r = getson(p);
if (nroot(f))
link(p, fa[f], getson(f));
else
fa[p] = fa[f];
link(ch[p][r ^ 1], f, r);
link(f, p, r ^ 1);
maintain(f);
maintain(p);
}
void splay(int p) {
pushall(p);
for (; nroot(p); rotate(p))
if (nroot(fa[p])) rotate(getson(p) == getson(fa[p]) ? fa[p] : p);
}
int access(int p) {
int y = 0;
for (; p; y = p, p = fa[p]) {
splay(p);
sizl[p] -= siz[y];
sizl[p] += siz[ch[p][1]];
ch[p][1] = y;
maintain(p);
}
return y;
}
void makeroot(int p) {
access(p);
splay(p);
reverse(p);
}
void link(int x, int y) {
makeroot(x);
makeroot(y);
fa[y] = x;
sizl[x] += siz[y];
}
void cut(int x, int y) {
makeroot(x);
access(y), splay(y);
fa[x] = ch[y][0] = 0;
maintain(y);
}
};
本文来自博客园,作者:caijianhong,转载请注明原文链接:https://www.cnblogs.com/caijianhong/p/template-lct.html