SP8791 DYNALCA - Dynamic LCA

\(\color{#0066ff}{ 题目描述 }\)

有一个森林最初由 n (\(1 \le n \le 100000\))n(\(1\leq n\leq 100000\)) 个互不相连的点构成

你需要处理以下操作:

link A B:添加从顶点A到B的边,使A成为B的子节点,其中保证A是一个根顶点,A和B在不同的树中。

cut A:切断点A到其父节点的边,保证A是一个非根节点。

lca A B:输出A和B的最近共同祖先,保证A和B在同一棵树中。

\(\color{#0066ff}{输入格式}\)

第一行包含三个正整数N、M,分别表示树的结点个数、询问的个数

接下来M行表示询问。

\(\color{#0066ff}{输出格式}\)

对于每个LCA询问输出答案

\(\color{#0066ff}{输入样例}\)

5 9
lca 1 1
link 1 2
link 3 2
link 4 3
lca 1 4
lca 3 4
cut 4
link 5 3
lca 1 5

\(\color{#0066ff}{输出样例}\)

1
2
3
2

\(\color{#0066ff}{数据范围与提示}\)

none

\(\color{#0066ff}{ 题解 }\)

LCT求LCA

cut的时候,因为删的是父子边,暴力找前驱就行了

#include<bits/stdc++.h>
using namespace std;
#define LL long long
LL in() {
	char ch; int x = 0, f = 1;
	while(!isdigit(ch = getchar()))(ch == '-') && (f = -f);
	for(x = ch ^ 48; isdigit(ch = getchar()); x = (x << 1) + (x << 3) + (ch ^ 48));
	return x * f;
}
const int maxn = 1e5 + 5;
struct LCT {
protected:
	struct node {
		node *ch[2], *fa;
		int rev;
		node(int rev = 0): rev(rev) { ch[0] = ch[1] = fa = NULL; }
		bool ntr() { return fa && (fa->ch[1] == this || fa->ch[0] == this); }
		bool isr() { return fa->ch[1] == this; }
		void trn() { std::swap(ch[0], ch[1]); rev ^= 1; }
		void dwn() { if(rev) { if(ch[0]) ch[0]->trn(); if(ch[1]) ch[1]->trn(); rev = 0; } }
	}s[maxn], *lst, *t[maxn];
	int top, fa[maxn];
	void rot(node *x) {
		node *y = x->fa, *z = y->fa; int k = x->isr(); node *w = x->ch[!k];
		if(y->ntr()) z->ch[y->isr()] = x;
		x->ch[!k] = y, y->ch[k] = w;
		y->fa = x, x->fa = z;
		if(w) w->fa = y;
	}
	void splay(node *o) {
		t[top = 1] = o;
		while(t[top]->ntr()) t[top + 1] = t[top]->fa, top++;
		while(top) t[top--]->dwn();
		while(o->ntr()) { if(o->fa->ntr()) rot(o->isr() ^ o->fa->isr()? o : o->fa); rot(o); }
	}
	void access(node *x) { for(node *y = NULL; x; x = (y = x)->fa) splay(x), x->ch[1] = y, lst = x; }
	void makeroot(node *x) { access(x), splay(x), x->trn(); }
	node *findroot(node *x) { 
		access(x), splay(x); 
		while(x->dwn(), x->ch[0]) x = x->ch[0]; 
		return splay(x), x;
	}
	void link(node *x, node *y) { makeroot(x), x->fa = y; }
	node *pre(node *x) { 
		access(x), splay(x); x->dwn(), x = x->ch[0]; 
		while(x->dwn(), x->ch[1]) x = x->ch[1]; 
		return splay(x), x;
	}
	void cut(node *x) {
		access(x), splay(x), x->dwn();
		node *y = x->ch[0];
		while(y->dwn(), y->ch[1]) y = y->ch[1];
		splay(y);
		y->ch[1] = x->fa = NULL;
	}
public:
	int LCA(int x, int y) { return access(s + x), access(s + y), lst - s; }
	void link(int x, int y) { link(s + x, s + y); }
	void cut(int x) { cut(s + x); }
}v;
char getch() {
	char ch;
	while(!isalpha(ch = getchar()));
	return ch;
}
int main() {
	int n = in(), m = in();
	int x, y;
	while(m --> 0) {
		if(getch() == 'l') {
			if(getch() == 'c') x = in(), y = in(), printf("%d\n", v.LCA(x, y));
			else x = in(), y = in(), v.link(x, y);
		}
		else v.cut(in());
	}
	return 0;
}
posted @ 2019-01-12 08:47  olinr  阅读(160)  评论(0编辑  收藏  举报