• 周日. 6月 26th, 2022

5G编程聚合网

5G时代下一个聚合的编程学习网

热门标签

【Luogu P5787】二分图 /【模板】线段树分治

admin

11月 28, 2021

链接:

洛谷

题目大意:

有一个 (n) 个节点的图,在 (k) 时间内有 (m) 条边会出现后消失,要求出每一时间段内这个图是否是二分图。

思路:

线段树分治用于离线、可撤销类的题目。

线段树维护某时间内连的边。统计答案时,用扩展域并查集查询连边是否合法。并查集不可路径压缩,因为要用栈回溯。

代码:

const int N = 3e5 + 10;

inline ll Read()
{
	ll x = 0, f = 1;
	char c = getchar();
	while (c != '-' && (c < '0' || c > '9')) c = getchar();
	if (c == '-') f = -f, c = getchar();
	while (c >= '0' && c <= '9') x = (x << 3) + (x << 1) + c - '0', c = getchar();
	return x * f;
}

int n, m, k;

struct node
{
	int l, r, st, ed;
}e[N];

vector <int> t[N << 3];
void Modify(int p, int l, int r, int L, int R, int id)
{
	if (l > R || r < L)  return;
	if (L <= l && r <= R) 
	{
		t[p].push_back(id);
		return;
	}
	int mid = l + r >> 1;
	Modify (p << 1, l, mid, L, R, id);
	Modify (p << 1 | 1, mid + 1, r, L, R, id);
}

struct Stack
{
	int x, y, add;
};
int top = 0;
Stack stk[N << 2];

int fa[N << 1], height[N << 1];

int Find(int k) {return k == fa[k]? k: fa[k] = Find(fa[k]);} 
void Merge (int u, int v)
{
	int x = Find(u), y = Find(v);
	if (height[x] > height[y]) x ^= y ^= x ^= y;
	stk[++top] = (Stack){x, y, height[x] == height[y]};
	fa[x] = y;
	if(height[x] == height[y]) height[y]++;
}

void Solve (int p, int l, int r)
{
	int flag = 1, lsttop = top;
	for (int i = 0; i < t[p].size(); i++)
	{	
	int u = e[t[p][i]].l, v = e[t[p][i]].r;
		int x = Find(u), y = Find(v);
		if (x == y)
		{
			for (int j = l; j <= r; j++)
				printf ("No
");
			flag = 0;
			break;
		}
		Merge (u, v + n);
		Merge (v, u + n);
	} 
	if (flag)
	{
		if (l == r) printf ("Yes
");
		else 
		{
			int mid = l + r >> 1;
			Solve (p << 1, l, mid);
			Solve (p << 1 | 1, mid + 1, r);
		}
	}
	for (; top > lsttop; top--)
		height[fa[stk[top].x]] -= stk[top].add,
		fa[stk[top].x] = stk[top].x;
}

int main()
{
	n = Read(), m = Read(), k = Read();
	int cnt = 0;
	for (int i = 1; i <= m; i++)
	{
		e[i].l = Read(), e[i].r = Read(), e[i].st = Read(), e[i].ed = Read();
		Modify(1, 1, k, e[i].st + 1, e[i].ed, i);
	}
	for (int i = 0; i <= n * 2; i++) fa[i] = i, height[i] = 1;
	Solve (1, 1, k);
	return 0;
}

发表评论

您的电子邮箱地址不会被公开。