「BalticOI 2020」小丑

Posted zqs2020

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了「BalticOI 2020」小丑相关的知识,希望对你有一定的参考价值。

预处理出 \\(f_i\\) 表示最大的使得在加入所有 \\([1,i)\\or [j,m]\\) 中的边后存在奇环的最大 \\(j\\)

显然 \\(f\\) 满足单调性,于是可以整体二分。

对于分治区间 \\([l,r]\\),已知所有 \\(\\f_l...f_r\\\\in [x,y]\\),那么暴力计算出 \\(f_mid\\),然后递归分治。

暴力计算时用并查集判断奇环即可。需要支持回撤操作,所以使用可撤销并查集。

注意: 由于存在 \\([1,i)\\) 中的边已经构成奇环的特殊情况,在 \\(x=y\\) 时不能直接 return!

#include <cstdio>
#include <algorithm>
#define gc (p1 == p2 && (p2 = (p1 = buf) + fread(buf, 1, 65536, stdin), p1 == p2) ? EOF : *p1 ++)

char buf[65536], *p1, *p2;
inline int read() 
	int x = 0;
	char ch;
	while ((ch = gc) < 48);
	do x = x * 10 + ch - 48; while ((ch = gc) >= 48);
	return x;

struct node int x, y; stk[200005];
int fa[200005], from[200005], to[200005], dis[200005], sze[200005], f[200005], n, m, q, top;

node getval(int x) 
	int sum = 0;
	while (fa[x] != x) sum ^= dis[x], x = fa[x];
	return nodex, sum;

inline bool merge(int x, int y) 
	node fx = getval(x), fy = getval(y), tmp;
	if (fx.x == fy.x) return fx.y == fy.y;
	if (sze[fx.x] < sze[fy.x]) tmp = fx, fx = fy, fy = tmp;
	fa[fy.x] = fa[fx.x], dis[fy.x] = fx.y ^ fy.y ^ 1, sze[fx.x] += sze[fy.x];
	stk[++ top] = nodefx.x, fy.x; return false;


void rollback(int x) 
	while (top > x) fa[stk[top].y] = stk[top].y, sze[stk[top].x] -= sze[stk[top].y], dis[stk[top].y] = 0, -- top;

void solve(int l, int r, int x, int y) 
	if (l > r || x > y) return;
	int mid = l + r >> 1, now = top;
	bool flag = false;
	for (int i = l; i < mid; ++ i) flag |= merge(from[i], to[i]);
	if (flag) 
		for (int i = mid; i <= r; ++ i) f[i] = m + 1;
		rollback(now), solve(l, mid - 1, x, y);
		return;
	
	int suftop = top;
	for (int i = y; i >= x && i >= mid; -- i)
		if (flag |= merge(from[i], to[i])) f[mid] = i; break;
	rollback(suftop);
	if (merge(from[mid], to[mid])) for (int i = mid + 1; i <= r; ++ i) f[i] = m + 1;
	else solve(mid + 1, r, f[mid], y);
	rollback(now), now = top;
	for (int i = y; i > f[mid]; -- i) merge(from[i], to[i]);
	solve(l, mid - 1, x, f[mid]);
	rollback(now);


int main() 
	n = read(), m = read(), q = read();
	for (int i = 1; i <= n; ++ i) fa[i] = i, sze[i] = 1;
	for (int i = 1; i <= m; ++ i) from[i] = read(), to[i] = read();
	solve(1, m, 1, m);
	for (int i = 1, l, r; i <= q; ++ i) l = read(), r = read(), puts(r < f[l] ? "YES" : "NO");
	return 0;

以上是关于「BalticOI 2020」小丑的主要内容,如果未能解决你的问题,请参考以下文章

[BalticOI2014]Friends

LOJ#2369. 「BalticOI 2008」魔法石

[BalticOI 2014]Three Friends 题解

[BalticOI 2014]Three Friends 题解

BalticOI2003Gem 题解(树形DP)

《小丑》观后感