Logo ryp 的博客

博客

ABC350G 题解

...
ryp
2025-12-01 12:50:20
She's not square

本文章由 WyOJ Shojo 从洛谷专栏拉取,原发布时间为 2024-04-21 23:44:22

LCT 板子,然而我没不会 LCT,然而可以根号分治甚至跑得贼快。

既然已经保证了整个图是森林,我们就好办了,树上可简单得多。

我们先考虑只有操作二的情况:很明显,我们只需要找两个点所连接的点的交集,明显这个交集的模不大于一。这个过程是 $O(d(u)) = O(n)$ 的。可以用一个 bitset 优化,那么就比上一个 $\omega$ 的常数。

再看操作一。我们暴力改的话无非就是 bitset 设位,是 $O(1)$ 的…… 但是

…… 明显这个做法是行不通的,bitset 空间 $O(n^2)$,爆掉。

考虑根号分治。对于度不大于 $\sqrt N$ 的点,修改无视 $O(1)$,操作直接暴力 $O(\sqrt N)$,很优。

大于 $\sqrt N$ 的点,建立 bitset(我们最多只会建立 $\sqrt N$ 个 bitset) 是 $O(\sqrt N)$ 的。查找是最差 $O(\dfrac N {2\omega})$ 的(因为两个点的度都要大于 $\sqrt N$,于是比上一个 $2$)。

看起来很差,但是 $N$ 和 $Q$ 的和是有限制的(设 $T = 10^5$),解一下得到一个大致最大 $Q = \dfrac {T} 2$ 时候为 $\dfrac {T^2} {8\omega} \pprox 10^{7.29}$,叉不掉。简单写了一个 generator,但是根本叉不掉,只叉到 100ms 左右。

#include <iostream>
using namespace std;
const int N = 5e4, Q = 5e4;

int main (void)
{
	ios::sync_with_stdio (false), cin.tie (0), cout.tie (0);
	cout << N << ' ' << N + Q << '\n';
	for (int i = 4; i <= N \/ 2 + 1; i++) cout << "1 2 " << i << '\n';
	for (int i = N \/ 2 + 2; i <= N; i++) cout << "1 3 " << i << '\n';
	cout << "1 1 2\n1 1 3\n";
	for (int i = 0; i < Q + 1; i++) cout << "2 2 3\n";
	return 0;
}

这题到这里就真正做完了。

评论

暂无评论

发表评论

可以用@mike来提到mike这个用户,mike会被高亮显示。如果你真的想打“@”这个字符,请用“@@”。