P14302 基础倍增练习题 6 / 小 U 的树

题目描述

给定 $n$ 个点,点有权,初始时两两均未连边。 你需要支持 $m$ 次两种操作之一: 1. 在两个不联通的点间连上一条边; 2. 求两个给定点构成路径上所有点权的最大子段和(不能为空)。 强制在线。

输入格式

由于输入量较大,本题数据采用程序内随机生成的方式。 第一行三个正整数 $n,m,sd$,其中 $sd\in[0,2^{64})$ 为六十四位无符号整数。你需要将 $sd$ 重赋值为对其调用 `splitmix64` 得到的值。随后你需要调用 $n$ 次 `rnd()` 生成每个点的点权,在有符号三十二位整数范围内。 随后你需要生成 $m$ 次操作。每次操作调用两次 `rnd()` 模 $n$ 的值加一以生成两个随机点,随后若其不联通则执行操作 1,否则执行操作 2。 关于更多细节,见提示说明部分。 **上述数据生成方式仅是为了减少输入量大小,标准算法不依赖于该生成方式。**

输出格式

对于每次 2 操作,将答案异或给 $sd$。在程序的最后,一行输出 $sd$ 即可。 关于更多细节,见提示说明部分。

说明/提示

对于 $10\%$ 的数据,$n,m\le 10^3$; 对于 $20\%$ 的数据,$n,m\le 10^4$; 对于 $30\%$ 的数据,$n,m\le 10^5$; 对于 $50\%$ 的数据,$n,m\le5\times10^5$; 对于 $70\%$ 的数据,$n,m\le 10^6$; 对于 $100\%$ 的数据,$1\le n,m\le 3\times10^6$,$0\le sd\lt2^{64}$。 --- 以下是部分样板代码。 随机数部分: ```cpp uint64_t sd; uint64_t rnd() { sd ^= sd > 7; return sd ^= sd > 30)) * 0xbf58476d1ce4e5b9; x = (x ^ (x >> 27)) * 0x94d049bb133111eb; return x ^ (x >> 31); } ``` 主函数部分: ```cpp cin >> n >> m >> sd, sd = splitmix64(sd); for (int i = 1; i