• 微信公众号:美女很有趣。 工作之余,放松一下,关注即送10G+美女照片!

LCT

开发技术 开发技术 6小时前 2次浏览

填坑。
就是可以维护树上动态删边加边,链操作的数据结构。整体思想就是维护一个实链剖分,每个实链按深度用splay来维护。

有以下基本操作:

1.access(x),就是把根到x都搞成实链。直接自底向上,把当前splay接到上面splay的右儿子。
2.getroot(x) ,找x所在的根。access完以后把x splay到 splay的根,一直往左儿子找即可(因为根深度最小)。
3.makeroot(x) ,将x定为根。access后发现其它关系不变,x到根的这一段翻转了,直接splay x到根然后翻转splay。
4.link(x,y),先判它们是否已连接。暴力makeroot(x),让fa[x]=y
5.split(x,y),将x到y单独拉出来作为一个splay。直接makeroot(x)再access(y),splay一下就行。(链修改查询也用这个)
5.cut(x,y) split 完硬断开就行。

luogu模板

#include <iostream>
#include <cstdio>
#include <algorithm>
#include <cstring>
#include <stack>

using namespace std;

const int N = 2e5 + 5;

int ch[N][2], val[N], sum[N], fa[N], siz[N], n, m, tag[N];

inline int read() {
	register int s = 0;
	register char ch = getchar();
	while (!isdigit(ch)) ch = getchar();
	while (isdigit(ch)) s = (s << 1) + (s << 3) + (ch & 15), ch = getchar();
	return s;
}

#define ls(x) ch[x][0]
#define rs(x) ch[x][1]
#define isRight(x) (ch[fa[x]][1]==x)

inline bool nroot(int x) { return ls(fa[x]) == x || rs(fa[x]) == x; }

inline void update(int x) { siz[x] = siz[ls(x)] + siz[rs(x)] + 1; sum[x] = sum[ls(x)] ^ sum[rs(x)] ^ val[x]; }

inline void pushdown(int x) { if (tag[x]) swap(ls(x), rs(x)); tag[ls(x)] ^= tag[x]; tag[rs(x)] ^= tag[x]; tag[x] = 0; }

inline void rotate(int x) {
	int f = fa[x]; int ff = fa[f], c = isRight(x); if (nroot(f)) ch[ff][isRight(f)] = x;
	ch[f][c] = ch[x][c ^ 1]; fa[ch[x][c ^ 1]] = f; ch[x][c ^ 1] = f;
	fa[f] = x; fa[x] = ff; update(f); update(x);
}

inline void splay(int x) {
	stack<int> st; st.push(x); for (int i = x; nroot(i); i = fa[i]) st.push(fa[i]);
	while (!st.empty()) pushdown(st.top()), st.pop();
	for (int f = fa[x]; nroot(x); rotate(x), f = fa[x])
		if (nroot(f)) rotate((isRight(f) ^ isRight(x)) ? x : f);
	update(x);
}

inline void access(int x) { for (int i = 0; x; x = fa[i = x]) splay(x), rs(x) = i, update(x); }

inline int getroot(int x) { access(x); splay(x); while (ls(x)) pushdown(x), x = ls(x); splay(x); return x; }

inline void makeroot(int x) { access(x); splay(x); tag[x] ^= 1; }

inline void link(int x, int y) { if (getroot(x) != getroot(y)) makeroot(x), fa[x] = y; }

inline void split(int x, int y) { makeroot(x); access(y); splay(y); }

inline void cut(int x, int y) {
	if (getroot(x) == getroot(y)) {
		split(x, y);
		if (ch[y][isRight(x) ^ 1] || fa[x] != y || rs(x)) return ;
		fa[x] = ls(y) = 0; update(y);
	}
}

inline void modify(int x, int y) { val[x] = y; access(x); splay(x); update(x); }

inline int query(int x, int y) { split(x, y); return sum[y]; }

int main() {
	n = read(); m = read();
	for (int i = 1; i <= n; ++i) val[i] = sum[i] = read();
	int opt, x, y;
	while (m--) {
		opt = read(); x = read(); y = read();
		if (opt == 0) printf("%dn", query(x, y));
		else if (opt == 1) link(x, y);
		else if (opt == 2) cut(x, y);
		else if (opt == 3) modify(x, y);
	} return 0;
}

程序员灯塔
转载请注明原文链接:LCT
喜欢 (0)