loj#121.「离线可过」动态图连通性

题面

话说#122怎么做啊

题解

我的\(\mathrm{LCT}\)水平极差,连最小生成树都快忘了,赶紧复习一下

做法和这篇是一样的

这道题还可以练习线段树分治

还可以练习ETT

果然是道吼题

代码

LCT

#include<cstdio>
#include<cstring>
#include<cctype>
#include<algorithm>
#include<map>
#define RG register
#define file(x) freopen(#x".in", "r", stdin), freopen(#x".out", "w", stdout)
#define clear(x, y) memset(x, y, sizeof(x))

inline int read()
{
	int data = 0, w = 1; char ch = getchar();
	while(ch != '-' && (!isdigit(ch))) ch = getchar();
	if(ch == '-') w = -1, ch = getchar();
	while(isdigit(ch)) data = data * 10 + (ch ^ 48), ch = getchar();
	return data * w;
}

const int maxn(505010), INF(0x3f3f3f3f);
struct edge { int opt, from, to, beg, end; } e[maxn];
int n, m, val[maxn], fa[maxn], son[2][maxn];
int stk[maxn], top, del[maxn], cnt, tim;
bool rev[maxn]; std::map<int, int> G[maxn];

inline bool isroot(int x) { return son[0][fa[x]] != x && son[1][fa[x]] != x; }
inline int getson(int x) { return son[1][fa[x]] == x; }
inline void update(int x)
{
	del[x] = x;
	if(val[del[x]] > val[del[son[0][x]]]) del[x] = del[son[0][x]];
	if(val[del[x]] > val[del[son[1][x]]]) del[x] = del[son[1][x]];
}

inline void pushdown(int x)
{
	if(!rev[x]) return;
	rev[son[0][x]] ^= 1;
	rev[son[1][x]] ^= 1;
	rev[x] = 0, std::swap(son[0][x], son[1][x]);
}

inline void rotate(int x)
{
	int f = fa[x], g = fa[f], l = getson(x), r = l ^ 1;
	if(!isroot(f)) son[getson(f)][g] = x;
	fa[x] = g, fa[f] = x, fa[son[r][x]] = f;
	son[l][f] = son[r][x], son[r][x] = f;
	update(f); update(x);
}

void splay(int x)
{
	stk[top = 1] = x;
	for(RG int i = x; !isroot(i); i = fa[i]) stk[++top] = fa[i];
	for(RG int i = top; i; i--) pushdown(stk[i]);
	for(; !isroot(x); rotate(x)) if(!isroot(fa[x]))
		rotate(getson(fa[x]) ^ getson(x) ? x : fa[x]);
}

void access(int x)
{
	for(RG int t = 0; x; t = x, x = fa[x])
		splay(x), son[1][x] = t, update(x);
}

int find(int x) { access(x); splay(x); while(son[0][x]) x = son[0][x]; return x; }
inline void makeroot(int x) { access(x); splay(x); rev[x] ^= 1; }
inline void split(int x, int y) { makeroot(x); access(y); splay(y); }
inline void link(int x, int y) { makeroot(x); fa[x] = y; }
inline void cut(int x, int y) { split(x, y); son[0][y] = fa[x] = 0; update(y); }

int main()
{
	cnt = n = read(), m = read();
	for(RG int i = 1; i <= m; i++)
	{
		int opt = read(), x = read(), y = read();
		if(x > y) std::swap(x, y);
		++tim;
		if(opt == 0) e[G[x][y] = tim].end = INF;
		if(opt == 1) e[G[x][y]].end = tim;
		e[tim].beg = tim, e[tim].opt = opt, e[tim].from = x, e[tim].to = y;
	}
	for(RG int i = 0; i <= cnt; i++) val[i] = INF;
	for(RG int i = 1; i <= tim; i++)
	{
		int x1 = e[i].from, x2 = e[i].to;
		if(e[i].opt == 0)
		{
			if(x1 == x2) continue;
			if(find(x1) == find(x2))
			{
				split(x1, x2); int d = del[x2];
				if(val[d] >= e[i].end) continue;
				else cut(x1, d), cut(x2, d);
				val[++cnt] = e[i].end;
				link(x1, cnt), link(x2, cnt);
			}
			else val[++cnt] = e[i].end, link(x1, cnt), link(x2, cnt);
		}
		if(e[i].opt == 1)
		{
			if(find(x1) == find(x2))
			{
				split(x1, x2); int d = del[x2];
				if(val[d] > e[i].beg) continue;
				cut(x1, d), cut(x2, d);
			}
		}
		if(e[i].opt == 2) puts(find(x1) == find(x2) ? "Y" : "N");
	}
	return 0;
}

线段树分治

咕咕咕

posted @ 2019-01-31 09:25  xgzc  阅读(347)  评论(2编辑  收藏  举报