AGC 杂题乱做
[AGC072A] Rhythm Game
*2800
给定 \(n\) 个按钮,第 \(i\) 个按钮会在 \(t_i\) 秒出现在坐标 \(x_i\),每个按钮会在出现 \(d + 0.5\) 秒后消失。玩家从坐标 0 开始,以每秒至多 1 的速度在坐标轴上移动,可以任意顺序按下所有按钮,每次按完按钮后需要回到坐标 \(0\),求能否按完 \(n\) 个按钮。
\(n \leq 5000, \, x_i, \, t_i, \, d \leq 10^{12}.\)
牛逼题,拜谢 jds 场上秒了这题。
因为每次按了都要回来,所以对于一个按钮是可以单独考虑的,考虑收集这个按钮出发时间的限制,显然必须在 \([t_i - x_i, t_i + d - x_i]\)(可以更早出发,但是显然没必要,因为恰好更充分利用时间)这个区间内出发才可以恰好收集到这个按钮,然后来回跑两次需要花 \(2x_i\) 的时间,于是最多在 \(t_i + d + x_i\) 的时间要回到原点。
于是可以看作在 \([t_i - x_i, t_i + d + x_i]\) 中选择一个长度为 \(2x_i\) 的区间,要去和其它按钮选择的区间不交,是否有合法方案。
可以看作有若干个任务,第 \(i\) 个任务在 \(l_i = t_i - x_i\) 时刻派发,做这个任务需要 \(tim_i = 2x_i\) 的时间,且需要在 \(r_i = t_i + d + x_i\) 前完成,问是否能做 \(n\) 个任务。
看起来很难做啊,能不能找一些性质,如果 \(l_i\) 都是 \(0\) 的话,一个显然的贪心是按照 \(r_i\) 从小到大依次做任务,能做就做,因为如果 \(r_i > r_j\) 且先做的 \(r_i\) 的任务再做 \(r_j\) 的,那么显然交换做的顺序后依然合法且不劣。
现在加上 \(l\) 的限制了,依然按照 \(r\) 排序,但是上面那个贪心策略就会有问题,因为可能出现 \(r_i\) 最小的任务还没有发布,空闲时间内应该去做其它已经发布了的任务,那这个策略怎么刻画呢?
假设空闲时间内去做了任务 \(j\),你会发现做完 \(j\) 之后所有 \(i < j\) 的任务一定都发布了,那是因为 \(t_j + x_j + d \ge t_i + x_i + d\),考察做完 \(j\) 的最早时间显然是 \(t_j + x_j \ge t_i + x_i \ge t_i - x_j\),得证。
那么根据前面的贪心策略,空闲时间内如果先做了 \(j\) 任务了,那么 \(j\) 前面的任务一定已经发布了,应该按照 \(r\) 的大小从小到大依次做,直到最小的 \(r\) 任务又没有发布,那就先去做另外一个任务,然后这个任务前面的都会发布,以此类推……
上面那个过程显然可以用 dp 刻画,定义 \(f_i\) 表示完成了前 \(i\) 个任务所需要的最小时间,然后找一个 \(j\) 去完成任务 \(j\) 后发布了 \(<j\) 的任务,再依次去完成 \(i + 1, \cdots, j - 1\),于是:
然后考虑怎么算中间的是否能全部完成,显然做完 \(j\) 后的时间是 \(t = \max(l_j, f_i) + tim_j\),然后依次做 \([i + 1, j - 1]\),设当前做到 \(k\),需要满足 \(t + \sum_{i + 1 \le x \le k} tim_x \le r_k\),令 \(s\) 为 \(tim\) 前缀和,相当于满足 \(t + s_k - s_i \le r_k\),即 \(t - s_i \le r_k - s_k\);于是只需要找到中间 \(k\) 的 \(r_k - s_k\) 的最小值即可快速 check,枚举 \(i\) 的时候顺路处理即可。
时间复杂度为 \(O(n^2)\)。
[AGC063C] Add Mod Operations
*2500
给定两个长度为 \(n\) 的序列 \(a, b\),判断能否用至多 \(n\) 次操作让 \(a\) 变成 \(b\),操作如下:
- 选择两个整数满足 \(0 \leq x < y \leq 10^{18}\),将所有 \(a_i\) 变为 \((a_i + x) \bmod y\)。
如果有解需要构造。
\(n \leq 1000, 0 \leq a_i, b_i \leq 10^9.\)
先考虑什么情况无解;其实只有相同的 \(a\) 对应不同的 \(b\) 时无解,于是先把 \(a\) 相同的缩一块。
然后把 \(a\) 从小到大排序得到 \(a'\),注意到我们可以选择 \(x\) 和 \(a'_n + x\),这样造成的影响是将 \(a'_n \gets 0\) 然后扔到 \(a'_1\) 去,\(a'_{1 \sim n - 1}\) 全部加 \(x\) 且右移一位。
那么这样操作 \(n - 1\) 次后,显然得到的序列是 \([0, x_n, x_n + x_{n - 1}, \cdots, \sum_{i = 2}^{n - 1}x_i, a'_1 + \sum_{i = 1}^{n - 1}x_i]\)(设 \(id_i\) 表示这个序列第 \(i\) 位实际上是由原来的 \(a_{id_i}\) 得到的)。
你发现这样得到的前面 \(n - 1\) 个是单增的,但是我们最终目标 \(b\) 不是单增的,怎么办呢?相当于限制了 \(b\) 排序后下标和上面序列的 \(id\) 相同(注意要忽略 \(id_n\),因为它不是单增的)。
考虑钦定一个 \(p = 3 \cdot 10^9\),我们给每个 \(b_i\) 不断增加 \(p\) 直到所有 \(b'\) 是按照 \(id\) 排序的,最后直接模 \(p\) 就行;然后最后一步操作考虑 \(b'_{id_1}\) 和 \(p\)。
则序列会变成 \([b_{id_1}, (x_n + b'_{id_1}) \bmod {p}, \cdots, (\sum_{i = 2}^{n - 1} x_i) \bmod p, (a'_1 + \sum_{i = 1}^{n - 1}x_i + b'_{id_1}) \bmod p]\);相当于我们有限制:
于是想到钦定 \(x_{n - i + 1} = b'_{id_i} - b'_{id_{i - 1}}\)。
但是对于最后那个 \(a'_1 + \sum_{i = 1}^{n - 1}x_i + b'_{id_1} = a'_1 + x_1 + b'_{id_{n - 1}} = b_{id'_n}\),于是钦定 \(x_1 = b_{id'_n} - b'_{id_{n - 1}} - a_1'\) 即可,因为 \(x_1 \ge 0\),于是要满足 \(b'_{id_n} - b'_{id_{n - 1}} \ge a_1'\),调整 \(b'_{id_n}\) 一直加 \(p\) 即可。
于是这样可以在 \(n\) 次操作中构建出来。时间复杂度为 \(O(n^2)\)。
[AGC068B] 01 Graph Construction
*1800???
如果两个 \(01\) 串 \(S, T\) 的 \(0\) 和 \(1\) 的数量分别相等,那么设 \(S, T\) 生成的图为:
- 将 \(S\) 中的 \(0\) 和 \(T\) 中的 \(0\) ——对应连边。
- 将 \(S\) 中的 \(1\) 和 \(T\) 中的 \(1\) ——对应连边。
给定一个长度为 \(n\) 的序列 \(a\),你需要构造两个 \(01\) 串 \(S, T\),满足:
- \(S, T\) 的 \(0\) 和 \(1\) 的数量分别相等。
- \(|S| \leq 10^5\)。
- \(S, T\) 生成的图中 \(\forall i < j \leq n\),\(i, j\) 在同一连通块内当且仅当 \(a_i = a_j\)。
\(n \leq 100.\)
感觉挺脑电波的构造题,怎么场上被过穿了。
考虑初始构造 \(S\) 有 \(n\) 个 \(0\),\(T\) 有 \(n\) 个 \(1\),那么初始两边都有 \(n\) 个未匹配的位置;称作 \(p_1, \cdots, p_k\) 与 \(q_1, \cdots, q_k\) 吧,初始 \(k = n\)。
考虑给 \(S, T\) 右边分别加:
-
若给 \(S, T\) 末尾都加上 \(0\),那么会连上 \(p_1\) 与 \(n + 1\),然后 \(p\) 前面删掉 \(p_1\),后面再加上一个 \(n + 1\) 没有被匹配,欸,你发现 \(p_1\) 与 \(n + 1\) 连通性一致,于是本质上是将 \(p_1, \cdots, p_k\) 换成 \(p_2, \cdots, p_k, p_1\)。
-
若给 \(S\) 末尾加 \(1\),\(T\) 末尾加 \(0\),相当于连边 \(p_1\) 与 \(n + 1\),\(q_1\) 与 \(n + 1\) 连边,即合并了 \(p_1\) 与 \(q_1\) 的连通块;然后把 \(p_1, q_1\) 从 \(p, q\) 中删掉。
相当于你可以将 \(p\) 循环左移任意多次,于是你可以将 \(i\) 与任意 \(j\) 连边,于是对于限制的 \(A_i\),我们把 \(A_i\) 相同的提出来,拿一个排列搞成置换环,设这个排列 \(X\),表示 \(i\) 要连边 \(X_i\)。
于是对于 \(p_i, q_i\) 来说,只要 \(X_{q_i} = p_i\),那么就加 \(10\) 连边,否则就加 \(00\) 把 \(p\) 循环左移即可。
时间复杂度为 \(O(n^2)\)。
[AGC059D] Distinct Elements on Subsegments
*3300
给定一个长度为 \(n\) 的序列 \(b\) 和整数 \(k\),构造一个长为 \(n + k - 1\) 的正整数序列 \(a\),满足 \(\forall 1 \leq i \leq n\),\(b_i\) 等于 \(a_i, a_{i+1}, \dots, a_{i+k-1}\) 中不同的数的个数,或者报告无解。
\(n, k \leq 2 \times 10^5.\)
这题牛逼完了。
考虑显然有相邻两个满足 \(|b_i - b_{i + 1}| \le 1\),我们设 \(l_i\) 表示 \(a_{i - 1}, \cdots, a_{i - k + 1}\) 是否和 \(a_i\) 都不同,\(r_i\) 表示 \(a_{i + 1}, \cdots, a_{i + k - 1}\) 是否和 \(a_i\) 都不同,那么显然有 \(b\) 的转移:
那么如果 \(b_i \ne b_{i + 1}\),则 \(l_{i + k} - r_i = \pm 1\),而值域在 \([0, 1]\) 内,是可以唯一确定的;否则 \(b_i = b_{i + 1}\) 可以推出 \(l_{i + k} = r_i\)。
于是首先你可以得到一些 \(l, r\) 的性质,当然还有 \(\sum_{i = 1}^k l_i = b_1, \sum_{i = n}^{n + k - 1} r_i = b_n\),只需要满足这些条件 \(l, r\) 就一定存在对应的某个 \(a\) 了吗?
具体的,把每个数 \(v\) 出现位置单独拿出来 \(p_1, \cdots, p_k\),一定有 \(l_{p_i} = r_{p_{i - 1}}\),且 \(l_{p_1} = r_{p_k} = 1\),于是可以得到 \(l, r\) 中 \(0/1\) 数量都一样;即里面所有 \(l_{p_i} = 0\) 的位置,一定有 \(r_{p_{i - 1}} = 0\),且 \(p_i - p_{i - 1} < k\);扩展开来,对于所有 \(l_i = 0\) 的位置,一定存在 \(r_j = 0\) 使得 \(i - j < k\)。
于是对于一个固定的 \(l, r\) 来说,只要存在一个 \(l\) 中与 \(r\) 中 \(0\) 与 \(0\) 的匹配,且满足 \(1 \le x - y < k\),那么就一定可以像那样拆成上面那种形式从而构造出解。
显然最优的一定是 \(l\) 中第 \(i\) 个 \(0\) 匹配 \(r\) 中第 \(i\) 个 \(0\),不然交换了依旧合法;于是设 \(l, r\) 中 \(0\) 分别是 \(a_1, \cdots, a_k, b_1, \cdots, b_k\),则要满足 \(1 \le a_i - b_i < k\),且满足上面之前的所有限制(形如确定了一些位置的值,钦定两个位置值相同,前面 \(k\) 个和后面 \(k\) 个的和)。
限制考虑如何构造 \(l, r\) 使得满足上面那些限制,我们有钦定 \(r_i = l_{i + k}\):
-
如果 \(b_i = b_{i + 1} = k\),说明这 \(k\) 个数互不相同,那么一定有 \(r_i = l_{i + k} = 1\)。
-
否则,你发现赋值为 \(r_i = l_{i + k} = 0\) 一定不劣;先把外面能匹配的 \(0\) 全部匹配上,因为 \(b_i \ne k\),所以 \([i, i + k - 1]\) 中一定存在两个相同的数且互为前驱后继,设为 \(a_u = a_v\),那么 \(r_u = 0, l_v = 0\),且一定互相匹配(根据前面的形式),此时修改成 \((v, i), (i + k, u)\) 匹配是显然合法的,于是不劣;更优的是,相当于给中间不存在匹配 \(0\) 多了一些机会。
于是按照上面的分讨把所有 \(r_i = l_{i + k}\) 的限制解决掉了,剩下的就是 \(i \le k\) 的 \(l\) 和 \(i \ge n\) 的 \(r\) 是不确定的了,要求前面和是 \(b_1\),那么肯定尽量是把 \(1\) 全部放前面,这样把 \(0\) 尽可能往后面放可以造成的匹配更多一点(因为 \(i \le k\));对于 \(r\) 是一样的,把 \(1\) 全部放在最后面即可。
现在得到了满足限制的 \(l, r\),考虑如何构造出满足条件的 \(a\)?这是简单的,依次扫过去:
-
如果 \(l_i = 1\),那么随便拿一个和前面 \(k - 1\) 位不同的数即可。
-
否则 \(l_i = 0\),其和一个 \(r_j = 0\) 是匹配的,令 \(a_i \gets a_j\) 即可。
时间复杂度为 \(O(n)\)。
[AGC066A] Adjacent Difference
*2000
给定一个大小为 \(n \times n\) 的矩阵 \(A\) 和数字 \(d\),你可以对每个数字进行加上一个数或减去一个数的操作,使得每个数字与其相邻数字的差的绝对值 \(\geq d\),并且对于每个操作值的绝对值之和不超 \(\frac{dn^2}{2}\)。构造一个最终的矩阵。
\(n \leq 500.\)
对脑电波。
考虑黑白染色,黑色点将其变成 \(d\) 的偶数倍,白色点变成 \(d\) 的奇数倍,显然两种黑白染色方案总代价之和是 \(d n^2\),于是一定存在一种黑白染色使得代价 \(\le \frac{dn^2}{2}\)。
注意有负数的话取模要注意点。
时间复杂度为 \(O(n^2)\)。
[AGC066C] Delete AAB or BAA
*3000
给定一个由 \(A,B\) 构成的字符串 \(S\),每次可以删掉 \(S\) 中连续的一段 \(AAB\) 或 \(BAA\),删掉后 \(S\) 前后部分会拼起来,求最多能操作多少次。
\(|S| \leq 10^6.\)
找性质题。
这种问题,考虑找极小可消除段,即对于一个能删空的段 \([l, r]\),定义它是极小的,当且仅当存在一种删除方式,使得它不能被分成 \([l, mid], (mid, r]\) 两段,使得两段内可以单独删完。
那么对于一个消除完的区间 \([l, r]\),一定是由若干极小可消除段拼凑起来的,于是 dp 的时候就可以前面加一个极小可消除段而不是一个可删空的段这样比较难维护的信息。
考虑找到这个极小可消除段的充要条件,先找到一些必要的:
-
首先,要满足 \(A\) 的数量是 \(B\) 的两倍。
-
其次,由于是极小可消除段,那么最后一次删除一定是结合了开头结尾的,否则开头和结尾在两次被分别删了,一定可以分成两段分别删空;于是开头和结尾必须不同(相同的话 \(AAB, BAA\) 是消不掉的)。
显然,只要开头不等于结尾,且能删空,那么就是极小可消除段,于是只需要证明在这个基础上满足 \(A\) 的数量是 \(B\) 的两倍就可以把这个段删空,考虑归纳法:
-
当 \(n = 3\),显然合法。
-
否则找到第一个长度 \(\ge 2\) 的连续 \(A\) 段,显然它左边或者右边至少有一个不是开头结尾的 \(B\),否则会矛盾;于是可以删这个 \(AAB\) 或者 \(BBA\) 变成 \(n - 3\) 的子问题,由归纳得可以删空。
于是得证;那么令 \(B\) 为 \(-1\),\(A\) 为 \(-2\),此时前缀和是 \(S\),那么 \([l, r]\) 是极小可消除段只需要满足 \(s_l \ne s_r, S_r = S_{l - 1}\),令 \(dp_r\) 表示考虑前 \(r\) 个字符最少可以剩多少个,那么两种转移:
-
\(dp_r \gets dp_{r - 1} + 1\)。
-
找一个 \(l\) 满足 \(s_l \ne s_r, S_r = S_{l - 1}\),有 \(dp_r \gets dp_{l - 1}\)。
容易开个桶维护满足条件的 \(dp\) 最小值,时间复杂度为 \(O(n)\)。
[AGC066D] A Independent Set
*3500
给定一个长度为 \(n\) 的由 \(A,B\) 组成的字符串 \(S\),保证 \(A\) 的数量 \(\leq \frac{n+1}{2}\),交换 \(S_i\) 和 \(S_{i+1}\) 的代价为 \(x_i\),求让 \(S\) 中所有 \(A\) 不相邻的最小代价。
\(n \leq 10^6.\)
找性质题。
考虑最后合法的字符串是什么形式的,你发现一定是若干形如 \(ABAB\cdots AB\) 交替段和 \(B\cdots B\) 全 \(B\) 段拼起来的;但是这样可能会有一些问题,例如最后一个 \(A\) 后面可能没有 \(B\)?这个简单,在最后加上一个 \(B\) 就行了。
于是相当于把问题转化为若干个子问题,每个子问题在内部自己换,不会影响其它的部分(因为如果用其它部分的 \(B\) 过来显然不如自己的 \(B\) 优秀),此时就可以转移了,定义 \(w(l, r)\) 表示将 \([l, r]\) 换成 \(AB\cdots AB\) 形式的最小代价(显然前置条件是 \([l, r]\) 内 \(A\) 和 \(B\) 数量相等)。
然后定义 \(dp_i\) 表示考虑前 \(i\) 个字符的最小代价:
-
如果 \(s_i = B\),那么直接从 \(dp_{i - 1}\) 接过来。
-
如果 \([j, i]\) 的 \(A, B\) 数量相等,具体的,令 \(A \to -1, B \to 1\),求前缀和后有 \(s_i = s_j\),那么 \(dp_i \gets dp_j + w(j + 1, i)\)。
显然的,考虑以 \(i\) 为结尾拼了个 \(AB\cdots AB\) 段,如果其可以从中间分为两段分别独立操作,那么显然可以只转移后面的那段(因为一个 \(AB\cdots AB\) 段一定是若干独立 \(AB\) 段拼起来的),于是只需要找到最近的满足 \(s_i = s_j\) 的 \(j\) 即可(和这场 C 一个 trick)。
即我们钦定了一个 \(AB\cdots AB\) 段是独立的,当且仅当它涉及的交换不能被一个中间点分为两段独立操作,每次转移拼上一个独立段即可,而显然 \(i\) 结尾的独立段是满足 \(s_i = s_j\) 的最大 \(j\)。
于是现在问题转化为快速求 \(w(l, r)\),这个咋求,定义 \(swap_i\) 表示从 \(1\) 换到 \(i\) 的最小代价,找到 \([l, r]\) 中所有 \(A\) 的位置 \(p_1, \cdots, p_k\) 和每个 \(A\) 想要求的位置 \(q_i\),显然有一种最优的操作方式,使得你考虑对任意一个 \(A\) 向目标位置走的都是最短路,具体的,对于初始任意一个 \(A\) 向目标位置依次换过去,如果路程中碰到其它 \(A\),则让它先动,显然它们是往同方向动的,所以一定可以完成:
但是还是不能暴力求啊,那咋办?找一下独立段的性质,不能被分成两边分别处理,你考虑如果一个 \(A\) 往左边跑,一个 \(A\) 往右边跑,那么是不是一定能分成两段单独交换,所以你得到一个重要性质:对于一个独立段,里面的 \(A\) 一定全部往一个方向跑的。
于是可以把绝对值放到外面,有:
这样就好快速算了,显然是 \(q_i\) 是 \([l, r]\) 中和 \(l\) 同奇偶的那些位置,于是可以对每个奇偶单独开个前缀和,对于前面的和,可以对所有 \(A\) 单独开一个前缀和(记录下当且是考虑哪个区间的 \(A\) 了即可)。
时间复杂度为 \(O(n)\)。
[AGC036E] ABC String
*3800
给定一个只包含字符 \(A,B,C\) 的字符串 \(S\),你需要求出 \(S\) 最长的子序列,满足子序列中相邻的两个位置字符不同,且 \(A,B,C\) 的数量相等。
\(|S| \leq 10^6.\)
完全不是题,咋想到调整法的???
考虑从原序列删使得合法,那么显然对于一段连续相同的,可以先缩成一个字符。
然后设现在三个字符的出现次数为 \(C_A, C_B, C_C\),不妨钦定 \(C_A \le C_B \le C_C\),显然答案的上界是 \(C_A\),于是我们要删除掉一些数使得 \(C_A = C_B = C_C\) 合法且删除的字符尽可能少。
直接做还是还是没有任何思路,先考虑满足 \(C_A \le C_B = C_C\) 的情况
,你发现这种情况一定可以取到上界 \(C_A\) 这个答案:
- 考虑这种情况的形式,取相邻两个 \(A\) 之间,一定是 \(BC \cdots BC\) 这种形式的,即原来有 \(C_B\) 个 \(BC\) 的对,里面插入 \(C_A\) 个 \(A\) 最多破坏 \(C_A\) 个 \(BC\) 对,于是至少还剩下 \(C_B - C_A\) 对 \(BC\) 对可以删掉,于是一定能删到 \(C_A = C_B = C_C\)。
于是问题转化为,删除尽量少的 \(A\) 使得存在一种删除方法,使得删除后依旧相邻不同且 \(C_A' \le C_B' = C_C'\),考虑应该怎么删:
-
先把 \(C\) 两边字符不同的 \(C\) 给删掉。
-
如果此时依旧不能使得 \(C_C' = C_B\),那么只能删 \(AC\) 或者 \(CA\),因为删 \(CA\) 或者 \(BA\) 的话 \(C_B, C_C\) 会一起减,依旧无法满足条件,且会把相邻两个不同的条件变得更严。
于是策略是先删 \(C\) 两边不同的,然后再删 \(AC\) 或者 \(CA\),最后就只剩下 \(BC\) 或者 \(CB\) 了,于是一定可以使得 \(C_C' = C_B\),且显然这里减的 \(A\) 是最少的。
删 \(AC\) 与 \(CA\) 就是暴力的从前往后扫一遍,维护个栈即可,时间复杂度为 \(O(n)\)。
[AGC059A] My Last ABC Problem
*2000
定义一个由 \(A,B,C\) 构成的字符串 \(s\) 的美丽度为,最少用多少次如下操作可以使得 \(s\) 中所有字符相同:
- 选择一个 \(s\) 的子串 \(s_{l,\dots,r}\) 和一个 \(A,B,C\) 到 \(A,B,C\) 的双射,将 \(s_{l,\dots,r}\) 中的每个字符做一次映射。
给定一个长度为 \(n\) 的字符串 \(s\) 和 \(q\) 次询问,每次给出 \([l,r]\),求 \(s_{l,\dots,r}\) 的美丽度。
\(n, q \leq 10^5.\)
好好好,喜欢对脑电波。
首先可以将相同字符缩成一段,那么每次操作 \([l, r]\) 时可以将 \(l\) 和 \(r\) 分别变成和 \(s_{l - 1}, s_{r + 1}\) 相同的字符,那就可以合并了,相当于删除了两个字符。
而显然的,一次最多删两个字符,至少可以删一个,因为可能 \(s_l = s_r\) 且 \(s_{l - 1} \ne s_{r + 1}\) 或者 \(s_{l - 1} = s_{r + 1}\) 且 \(s_l \ne s_r\);事实证明,对于一个长度 \(n \ge 5\) 的字符串,一定可以找到 \(l, r\) 满足 \(s_l = s_r\) 或者 \(s_{l - 1} = s_{r + 1}\)(此时可以删两个),这是显然的。
当 \(n = 4\) 的时候,手摸一下,发现答案恰好是 \(2\),于是偶数时答案是 \(\frac{n}{2}\)。
否则,最后剩下 \(n = 3\) 的时候,显然最后只剩下 \(s_1, s_i, s_n\)(因为前面删不掉 \(s_1, s_n\)),于是需要判断 \(s_1\) 与 \(s_n\) 是否相同即可,相同的话直接操作中间的 \(s_i\),否则要操作两次;所以应该是 \(\frac{n - 3}{2} + 1 + [s_1 \ne s_n] = \frac{n - 1 + [s_1 \ne s_n]}{2}\)。
回到原问题了,要支持询问区间整个段相同字符缩在一起的长度,对于区间 \([l, r]\),考虑 \([s_i \ne s_{i - 1}]\) 时代表了一个段的开头,于是预处理 \([s_i \ne s_{i - 1}]\) 的前缀和 \(S\),则区间 \([l, r]\) 缩段后的长度为 \(S_r - S_l + 1\)。
于是时间复杂度为 \(O(n)\)。
[AGC057B] 2A + x
*2000
给定一个长度为 \(n\) 的数列 \(a\) 和正整数 \(X\),每次你可以选择一个 \(i\) 和 \(x\)(满足 \(0 \le x \le X\)),然后令 \(a_i \leftarrow 2a_i + x\),求在任意次操作后 \(a\) 的极差最小是多少。
\(n \leq 10^5, \ a_i, X \leq 10^9.\)
先将 \(a\) 从小到大排序,然后分析下性质,如果 \(a_n\) 操作过了,那么显然前面的 \(a_i\) 一定会操作至少一次,这是不劣的;所以要么 \(a_n\) 没操作,要么整个序列都操作了。
如果可以使得序列的极差 \(D <X\),那么显然操作整体操作一次后一定可以将 \(D\) 变小,所以经过若干次操作后答案一定是 \(0\)。
否则一定不会操作最大值,因为是倍增形的,每次操作后极差 \(2mx - (2(mx - D) + X) = 2D - X \ge D\),会比之前大。
于是只需要考虑不操作最大值的时候的解,即先将 \(a\) 从小到大排序,那么显然是要算出每个 \(a_i\) 操作到距离 \(a_n\) 最近的点,如果能变成 \(a_n\),那就直接变;否则设到 \(a_n\) 左右分别是 \(l_i, r_i\),那么问题转化为每个点选 \(l_i, r_i\),使得极差最小了。
则将 \(l\) 从小到大排序,枚举最小值,那么显然当前 \(i\) 前面的 \(l_j(j < i)\) 都选的 \(r_j\),于是容易算出极差。
考虑怎么求距离 \(a_n\) 最新的点,对于一个数 \(a_i\),每次是一个区间扩展的过程:\([a_i, a_i] \to [2a_i, 2a_i + X] \to [4a_i, 4a_i + 3X] \to \cdots\),这是一个倍增的过程最多有 \(O(\log w)\) 个区间。
如果算出来这个极差 \(<X\) 就可以操作成 \(0\),否则就是这个答案,时间复杂度为 \(O(n \log w)\)。
[AGC065B] Erase and Insert
*2200
有一个 \(1 \sim n\) 的排列 \(p\),初始时 \(p_i = i\),依次对 \(i \in [1, n]\) 做以下操作:从 \(p\) 中删去 \(i\),再在 \(p\) 的任意一个位置插入 \(i\)。给定最终序列 \(q\),求有多少种操作方法可以使 \(p\) 变成 \(q\)。对 \(10^9 + 7\) 取模。
\(n \leq 5000.\)
正着做太困难,考虑倒着做,即从 \(q\) 中从大到小开始,每次把 \(i\) 删掉然后再插入进去,问最后是 \(1 \sim n\) 的方案数。
那么显然,再操作 \(i\) 的时候,它插入的位置后面必须存在 \(i + 1 \sim n\),因为它们依旧先操作了,相对位置是不会变的。
于是只有这个限制的话,可以 dp 了,定义 \(f_{i, j}\) 表示操作了 \(i \sim n\) 了,最后 \(i\) 插入的位置在 \(1 \sim i -1\) 这些数所在位置的排名为 \(j\) 的方案数。
转移时,考虑刷表,对于一个 \(f_{i + 1, j}\),考虑 \(i\) 本身在 \(1 \sim i\) 位置的排名(显然后面的操作不会改变它们的相对顺序)设为 \(x\):
-
如果 \(x < j\),相当于 \(i + 1\) 插入的位置在 \(i\) 位置后面,所以 \(x\) 可以插入到 \(j\) 前面任何一个地方,即对于任意 \(k < j\),有 \(f_{i, k} \gets f_{i, k} + f_{i + 1, j}\)。
-
否则 \(x \ge j\),即 \(i + 1\) 插入在 \(i\) 前面,所以相当于需要将 \(x\) 插入到 \(j\) 前面(此时 \(j\) 前面会多一个数),所以它的排名可以是 \(j\),所以这是对于任意 \(k \le j\),有 \(f_{i, k} \gets f_{i, k} + f_{i + 1, j}\)。
你发现都是后缀加,是容易 \(O(1)\) 维护的,时间复杂度为 \(O(n^2)\)。
[AGC045C] Range Set
*2800
给定 \(n, a, b\),有一个长为 \(n\) 的字符串,初始时所有字符都为 \(0\),求执行以下操作任意次能得到多少不同的字符串:
- 选择一个长为 \(a\) 的子串,全部赋为 \(0\)。
- 选择一个长为 \(b\) 的子串,全部赋为 \(1\)。
答案对 \(10^9 + 7\) 取模。
\(n \leq 5000.\)
这种算最终能形成多少本质不同的东西,都是考虑倒着做,即给定一个字符串,判断它是否能被操作给表示出来。
这题也是一样,考虑怎么判定字符串 \(s\) 能被操作出来,你发现正着完全无法做,那么倒着考虑,知道最后一次操作后,这些位置在之前可以被任意赋值,这样限制很少了。
具体的,显然最后一次一定是连着的长为 \(a\) 的 \(0\) 或者长为 \(b\) 的 \(1\),随意找到一个这样区间 \([l, r]\),将里面字符改为 \(?\) 表示通配符,倒数第二次也是一样找长 \(a, b\) 的连续段(算上通配符),然后继续改为 \(?\)。
所以本质上,判定 \(s\) 是否合法,当且仅当,可以通过每次选择一个长为 \(a\) 的 \(0\) 或者长为 \(b\) 的 \(1\)(也可以包含 \(?\) 通配符)段,将其改成 \(?\),使得最终全是 \(?\)。
先钦定 \(a \ge b\),考虑下这个的最优策略是什么?显然,对于任何长度 \(\ge b\) 的全 \(1\) 段一定可以变成全 \(?\),并且操作这个是不劣的,然后考虑剩下的 \(1\) 和 \(0\) 怎么办:
-
如果剩下 \(0\) 且不能进行一次长为 \(a\) 的覆盖,那么显然无解。
-
否则,设找到了一个 \(0\) 和 \(?\) 的长为 \(a\) 的覆盖是 \([l, r]\),那么显然,其可以从中间向两边拓展开来,把所有的都覆盖成 \(?\)(因为 \(a \ge b\),所以剩下的连续 \(1\) 最多 \(b - 1\) 个,一定可以通过中间覆盖过去的 \(?\) 把这些 \(1\) 改成 \(?\))。
所以有解当且仅当把长度 \(\ge b\) 的全 \(1\) 段覆盖为 \(?\) 后,存在一个长为 \(a\) 的 \(0\) 和 \(?\) 的连续段,这是充要的,所以可以直接对这个计数;但是存在还是不太好做,显然容斥一下算一下不存在长度 \(\ge a\) 的即可。
然后考虑怎么计数?显然对于长度 \(\ge b\) 的全 \(1\) 段,可以看作是 \(0\),于是转移的时候,要么是加上一个长度 \(<b\) 的全 \(1\) 段,要么是加上一个 \(<a\) 的“全 \(0\) 段”,于是为了辅助,定义 \(f_i\) 表示长度为 \(i\) 的满足所有连续 \(1\) 段长度 \(\ge b\) 的 \(01\) 序列数(当然也可以不存在 \(1\))。
于是你的结构一定是 \(<a\) 的“全 \(0\) 段”与 \(<b\) 的全 \(1\) 段交替拼起来。
然后再定义 \(dp_{i, 0/1}\) 表示以 \(i\) 结尾不合法的本质不同字符串个数,且结尾是 \(0/1\),有转移:
- 当 \(i\) 结尾是 \(0\) 时,枚举 \(j\),表示 \([i, j]\) 是一个 \(<a\) 的“全 \(0\) 段”,显然上一段结尾要是 \(1\),不然会和这段拼起来,且 \(j\) 位置处也要是 \(0\),不然会和上一段结尾的 \(1\) 拼起来(只有当 \(j = 1\) 的时候没有限制,因为没有上一段),所以:
- 否则 \(i\) 结尾是 \(1\) 时,枚举 \(j\),表示 \([i, j]\) 是一个 \(<b\) 的全 \(1\) 段,显然上一段结尾要是 \(0\),不然会拼起来,所以:
最后答案怎么算,你发现直接 \(2^n - dp_{n, 0} - dp_{n ,1}\) 是有问题的,具体的,你发现上面转移实际上是有问题的;对于一个“全 \(0\) 段”最后一段结尾不一定是 \(0\),还可能是 \(1\);那显然只有最后一个“全 \(0\) 段”结尾时末尾可以是 \(1\),因为如果在中间结尾是 \(1\) 后面还拼了个 \(<b\) 的全 \(1\) 段是不合法的。
再定义对于一个长度为 \(i\) 的以 \(0/1\) 结尾的“全 \(0\) 段”是 \(g_{i, 0/1}\),显然:
顺便转移下 \(f\),显然有:
所以实际上答案是:
时间复杂度为 \(O(n^2)\)。
[AGC071C] Orientable as Desired
*2800
给定一个 \(n\) 个点 \(m\) 条边的无向简单连通图,判断是否存在一个长度为 \(n\) 的非负整数序列 \((x_1, x_2, \dots, x_n)\),满足:
- \(x_i \leq \text{deg}_i\),\(\text{deg}_i\) 表示点 \(i\) 的度数。
- 不存在一种给原图的每条边定向的方案,使得 \(\forall 1 \leq i \leq n\),满足点 \(i\) 的出度或入度等于 \(x_i\)。
\(n, m \leq 2 \times 10^5.\)
第一眼看上去完全不可做的样子。
那么考虑给 \(x_i\) 找一些特殊值,看能不能使得图满足一些特殊的性质;一种显然的想法是先找 \(x = (0, \cdots, 0)\),于是只有对于任意点都满足只有出度或者只有入度的时候,不满足这个 \(x\) 的要求。
而显然,任意点都满足只有出度或者只有入度,于是一定可以分成两个部分,左边是只有出度的,右边是只有入度的,然后在两个部分之间有左到右的边,一个部分内部没有边,这显然是一个二分图。
所以,当原图不是二分图的时候,选 \(x\) 全 \(0\) 就满足要求,输出 Yes 即可;否则原图是二分图,此时全 \(0\) 就不合法了,但是多了性质,考虑怎么做?
一样的,如果全 \(0\) 不行,那只有一位赋值行不行,这里假设是 \(x_1 = k\),其它是 \(0\),此时把先把和 \(1\) 相关的边断开单独处理,那么原图就被分为了若干连通块,显然每个连通块也是个二分图,于是每个连通块存在两种定向方法使得 \(x_i = 0, i > 1\) 被满足。
但是加上 \(1\) 的边和点了呢,因为原图是二分图,对于每个连通块来说,显然 \(1\) 只会和其中一个部分有边,设对于第 \(i\) 个连通块,有 \(p_i\) 条边,显然,因为两种定向都可以使得 \(x_i = 0\) 的条件满足,所以要么 \(1\) 全部连向这个连通块,要么这个连通块全部连向 \(1\)。
于是假设有 \(l\) 个连通块,分别是 \(p_1, \cdots, p_l\),如果 \(p\) 中可以选择若干个数使得和为 \(k\) 那么 \(x_1 = k\) 的条件就会被满足,那么这个 \(x\) 就不合法,而 \(k\) 是可以取遍 \([0, deg_1]\) 的,所以 \(p\) 需要凑出 \([0, deg_1]\) 中的所有数才行。
而 \(1\) 是可以任意的,所以当我们只赋值一项 \(x_u\) 有值时,\(x\) 合法当且仅当这个 \(u\) 断开后的 \(p_1, \cdots, p_l\) 不能凑出所有的 \([0, deg_u]\)。
继续考虑,如果只有一项有值的时候都无解,那么更多项有值会不会有解呢?假设 \(x_u = a, x_v = b\),把 \(u, v\) 断开后形成若干连通块,每个连通块内和 \(u, v\) 相关的边分别是 \(p_1, \cdots, p_l, q_1, \cdots, q_l\),你发现还是之前那个问题,要 \(p\) 凑出 \([0, deg_u]\),\(q\) 凑出 \([0, deg_v]\)。
之前一项有值时,断一个点都可以凑出 \([0, deg_u]\),如果 \(u, v\) 之间没有边,相当于把之前的 \(p'\) 分成更多的 \(p\) 了,一样还是可以凑出;否则 \(u, v\) 有边的话,还是一样,只是某个下面的某个 \(p\) 减少了 \(1\),钦定 \(u \to v\) 或者 \(v \to u\) 也可以凑出来,
三项或者更多项有值的时候是类似的,设有值的是 \(S\) 集合,然后对于 \(S\) 内部也是二分图,可以划分成子问题,都可以证明一定可以凑出来;所以只需要判定一项有值的时候是否存在合法的 \(x\) 即可。
考虑如何判定,对于一个 \(u\) 找到的 \(p_1, \cdots, p_l\),如何凑出 \([0, deg_u]\)?乍一看是背包问题,实际上是贪心问题,因为覆盖的要是一个整数的前缀,先将 \(p\) 从小到达排序,设考虑了前 \(i\) 个,目前覆盖了 \([0, \sum_{j \le i} p_j]\)(初始 \(p_0 = 0\) 开始),想要继续覆盖,显然要满足 \(\sum_{j \le i} p_j \ge p_{i + 1} - 1\),否则中间就有空的凑不出来,此时就可以覆盖 \([0, \sum_{j \le i + 1} p_j]\)。
因为 \(\sum p_j = deg_u\),所以对于所有的 \(i\) 都需要满足上面那个条件即可;但是还有一个问题,对于 \(u\) 如何快速把它对应的 \(p\) 找出来?每次暴力搜连通块是 \(O(m)\) 的,而 \(\sum_u \sum p_i = O(m)\),所以只要均摊的找出来就没有问题。
因为是删点,所以考虑 tarjan 求点双的时候在割点那算一下就行了,需要快速判一个边是否存在,用 set 存一下。
时间复杂度为 \(O(m \log m)\)。
[AGC043D] Merge Triplets
*2700
给定 \(n\),求有多少个 \(1 \sim 3n\) 的排列 \(p\) 能通过以下方式生成:
- 构造 \(n\) 个长为 \(3\) 的数组 \(a_1, \dots, a_n\),其中 \(1 \sim 3n\) 每个数恰好出现一次。
- \(p\) 初始为空,重复 \(3n\) 次以下操作:从所有非空的 \(a_i\) 中选出开头元素最小的 \(x\),将 \(x\) 加入 \(p\) 的末尾,并将 \(x\) 从所在的 \(a_i\) 中删除。
答案对给定的质数取模。
\(n \leq 2000.\)
考虑找到最终什么样子的排列是合法的,可以被生成的,找一下性质。
一个比较显然的性质是:
- 对于每个数组的第一个元素,加入 \(p\) 时一定是作为前缀最大值出现的。
证明比较简单,因为它一直是 \(n\) 个开头元素中的一个,所以前面选的都是比它小的,则它必然是一个前缀最大值。
然后继续找性质,如果 \(a_{i, 1}\) 被选了:
-
且 \(a_{i, 2}, a_{i, 3} < a_{i, 1}\) 即 \(a_{i, 1}\) 是三个中的最大值,那么接下来一定会把 \(a_{i, 2}, a_{i, 3}\) 一起选了(因为 \(a_{i, 1}\) 已经是开头中最小的了,把它删了加入更小的,那最小的肯定是那个更小的)。
-
否则其它情况,要么 \(a_{i, 2}\) 跟着 \(a_{i, 1}\) 一起选,要么 \(a_{i, 3}\) 跟着 \(a_{i, 2}\) 一起选,或者 \(a_{i, 1} < a_{i, 2} < a_{i, 3}\) 不会出现跟随的情况。
那这个跟随本质是什么,第一个本质上是在前缀最大值 \(a_{i, 1}\) 后面跟了一个或者两个非前缀最大值,那 \(a_{i, 2}\) 插入进 \(p\) 的时候呢?因为它没有跟随 \(a_{i, 1}\) 走,所以 \(a_{i, 2} > a_{i, 1}\) 且它也在 \(a_{i, 1}\) 走后一直是开头候选之一,前面选的都是比它小的,所以 \(a_{i, 2}\) 也是前缀最大值,于是如果 \(a_{i, 3}\) 跟着 \(a_{i, 2}\) 走的,本质上是一个前缀最大值后面跟了一个非前缀最大值的情况。
所以回到最终序列 \(p\),每次它前缀最大值出现时,后面最多跟两个非前缀最大值,相当于对于非前缀最大值构成的连续段长度不超过 \(2\) 且数量不超过 \(n\)。
你发现这个条件是充要的,通过这个你一定可以构造出一组 \(a\) 来,具体的:
-
前缀最大值后面跟两个的情况,直接三个放一块。
-
跟一个的情况,如果前面还有单独的前缀最大值,则随便拿个拼起来放一起就行,否则找一个后面的单独前缀最大值拼一起。
-
最后剩下的单独的,三个依次拼起来就行。
考虑怎么对这个计数?定义 \(f_{i, j}\) 表示只考虑了前 \(i\) 个数的相对顺序时,非前缀最大值连续段数量为 \(j\) 的方案数,有转移:
- 直接放一个前缀最大值:
- 放一个前缀最大值跟一个非前缀最大值:
- 放一个前缀最大值跟两个非前缀最大值:
直接转移就是 \(O(n^2)\) 的,可以通过。
[AGC068C] Ball Redistribution
*3200
有 \(n\) 个编号为 \(1 \sim n\) 的球和 \(n\) 个编号为 \(1 \sim n\) 的盒子,初始时你可以选择每个球放入哪个盒子,然后依次对 \(1 \sim n\) 执行以下操作:
- 如果盒子 \(i\) 中没有球,则跳过。
- 否则,你可以按任意顺序排列盒子 \(i\) 中的球,设排好后的顺序依次为 \(x_1, x_2, \dots, x_k\),则对于每个 \(1 \leq j \leq k\),将球 \(x_j\) 放入盒子 \(x_{j \bmod k + 1}\) 中。
给定最终状态中每个球在哪个盒子中,你需要确定是否存在一种初始的状态和操作顺序能得到最终状态。
\(n \leq 2.5 \times 10^5.\)
感觉很多题解直接讲结论,怎么想到的一概不说???这里给一个有思维链的做法。
只给了最终状态而判定初始状态,显然不能正着做,考虑倒着还原。
你发现这个将球 \(x_j\) 放入盒子 \(x_{j \bmod k + 1}\) 中,如果建立 \(i \to pos_i\)(\(pos_i\) 是 \(i\) 所在的盒子),那么一次操作就相当于创建了一个环,而我们这个图是内向基环树森林。
具体的,倒着从 \(n\) 开始做,设当且到 \(i\):
-
如果 \(i\) 在某个环内:那么说明 \(i\) 所在环上的点恰好就是这次操作的球,因为如果不是的话,是之前某个位置操作的,那么到 \(i\) 这里的球 \(x\) 在操作一次后就会跑到 \(x\) 那去了,而不是还在 \(i\) 这;所以会把 \(i\) 所在的环全部断掉,然后环上点增加到 \(i\) 的边,表示之前这些球都在 \(i\) 内。
-
否则 \(i\) 不在任何一个环内,那么:
-
\(i\) 操作的时候盒子里就没有球:啥也不干。
-
否则 \(i\) 盒子之前有球,经过这次操作后形成了一个环,而这个环我们不知道具体是哪个,所以任何一个都行;所以回退的话是选择一个环,然后把这个环断掉,然后环上点增加到 \(i\) 的边。
-
-
显然,如果此时存在一个点 \(j\) 指向 \(i\) 且 \(j\) 不在任何一个环中就无解,因为操作了之后一定是环。
于是我们要尽可能避免最后那种情况,即操作到 \(i\) 时尽可能不存在 \(j\) 不在环中指向它;对于最后状态的图,先找到 \(i\) 所在的点,其有一些儿子 \(j \in son_i\),我们想要把 \(j \to i\) 的边尽可能多的断掉,最多剩一条,且那一条最后必须在换上。
那么显然只有 \(j\) 和 \(i\) 一起在环上的时候才可以把 \(j \to i\) 的边断掉,因为可以用之前一次点的断环操作。
怎么才能保证 \(j\) 和 \(i\) 在一个环上呢,注意到,如果一次任意断环操作,是断的和 \(i\) 不在一个连通块内的环的话,会把那个环彻底断掉且连向 \(i\),无法创造一个新的环,也就无法使得某两个特定点在一个连通块内。
否则,如果断的是 \(i\) 所在连通块的环的话,你会发现,设 \(i\) 一路跳父亲跳到环上的点是 \(p\),那么会新增一个 \(i \to p \to i\) 的环;于是考虑能否使用断所在连通块的环创造一些边在环上。
而对于在环上的断环操作,你会形成一个 \(i \to i\) 的自环,不会影响环在当前连通块的存在性,所以没问题。
具体的,想要使得 \(j \to i\) 在环上,那么必须存在一个 \(j\) 子树内 \(k > i\)(比 \(i\) 先操作),此时会新增 \(k \to j \to i \to p \to k\) 的环(\(p\) 定义同上,即在环上的点),然后之后再操作的话就会把 \(j \to i\) 的边断掉了。
于是对于任何一个点 \(i\),和它的每个儿子 \(j\),子树内都必须存在至少一个 \(k > i\) 先操作把 \(j \to i\) 的边断掉,或者说最后一次操作后 \(j \to i\) 在一个环上,然后马上操作 \(i\),此时也是合法的。
于是我们得到了一个充要条件,定义 \(mx_v\) 表示 \(v\) 子树编号最大点,对于每个点 \(u\),它的所有儿子 \(v\) 都要满足 \(mx_v > u\)。
直接 \(O(n)\) 检查即可。
[AGC070B] Odd Namori
*3200
给定一棵 \(n\) 个点,以 \(1\) 为根的有根树,定义点 \(i\) 的父亲为 \(p_i\)。我们定义满足以下条件的有向图 \(G\) 为“好图”:
- 每个顶点的出度都为 \(1\)。
- 图中不存在偶数长度的环。
- 对于所有 \(2 \leq i \leq N\) 的 \(i\),\(G\) 中不包含边 \(i \to p_i\)。
计算所有可能的“好图” \(G\) 中 \(2^{\text{环的数量}}\) 的总和,对 \(998244353\) 取模。
\(n \leq 10^5.\)
根本不是题。
首先 \(G\) 中不包含边 \(i \to p_i\) 看起来就很难做啊,先扔掉看看怎么做。
你发现 \(2^{\text{环的数量}}\) 感觉压根不好算啊,怎么转化一下,假设有 \(k\) 个环,第 \(i\) 个环代价是 \(w_i\)(偶环就是 \(0\),奇环就是 \(2\)),那么答案就是:
考虑经典技巧,算乘积不好算的时候,可以钦定一些位置贡献 \(-1\),即有 \(\prod_{i = 1}^k w_i = \sum\limits_{S \subseteq \{1, \cdots, k\}} \prod\limits_{i \in S} (w_i - 1)\),于是可以:
其中 \(f(S)\) 表示钦定 \(S\) 集合内的点组成了若干个环,同时偶环贡献是 \(-1\),奇环贡献是 \(1\) 的方案数,然后 \(S\) 外面的点显然可以随意连边。
然后 \(f(S)\) 怎么算?你打个表或者注意惊人的话会发现 \(|S| > 1\) 时 \(f(S) = 0\),具体证明考虑:
-
设 \(S\) 中编号最小点为 \(x\),次小编号为 \(y\)。
-
那么交换 \(x\) 与 \(y\) 的连边,分讨一下:
-
如果 \(x, y\) 在一个环上,那么会把这个环分成两半(偶数可以拆成两个偶数或者两个奇数,奇数只能拆成一个奇数一个偶数)。
-
如果 \(x, y\) 不在一个环上,那么会把这两个环合并(偶数加偶数还是偶,奇数加奇数也是偶,奇数加偶数还是奇)。
-
-
于是你发现交换了之后,偶环的数量的奇偶性一定会改变;这证明了对于任何一个 \(S\) 中成环的方案,都与交换 \(x, y\) 的连边后的图一一对应,且奇偶性刚好相反,所以贡献全部抵消,是 \(0\)。
所以只需要考虑 \(|S| = 1\) 的情况,那么不包含边 \(i \to p_i\) 时可以快速算出答案了。
现在怎么算 \(f(S)\)?考虑不包含还是太难做了,再容斥一下,钦定包含了某些集合 \(T\) 的边,容斥系数是 \((-1)^{|T|}\);相当于把这些边连着的缩成了一个点考虑,显然此时 \(S\) 中要缩成一个点,不然根据之前的结论 \(f(S) = 0\);然后 \(S\) 外面的点只有 \(1\) 可以随便连方案是 \(n\),其它点都是 \(n - 1\)。
因为要缩成一个点,所以得到 \(T\) 中的边是一条链,设链长度是 \(p\),那么系数是 \((-1)^p (-1)^{(p + 1)} = 1\)(前面是容斥系数,后面是奇偶环的系数);即树上的一条祖先链,于是本质上只需要求出所有包含 \(1\) 的祖先链的链中每个长度的个数,以及不包含 \(1\) 的链的每个长度个数,这是比较好维护的,一个直接就是 \(dep_i\) 分类,一个是给一个前缀加,直接差分即可。
时间复杂度为 \(O(n)\)。
[AGC067A] Big Clique Everywhere
*2000
给定一个 \(n\) 个点 \(m\) 条边的简单无向图,判断此图是否满足以下条件:
- 对于任意一个 \(\{1, 2, \dots, n\}\) 的子集 \(X\),都存在一个 \(X\) 的子集 \(Y\) 满足 \(|Y| \geq \frac{|X|}{2}\) 且 \(Y\) 中的点构成了一个团。
\(n \leq 10^5, \ m \leq 10^6.\)
显然是需要找到一个判定图合法的充要条件。
这个团的限制看起来不太好做,考虑取补图后,对于一个团在补图中是一个独立集。
于是问题转化为,对于任意 \(S\),是否能在补图中找到一个 \(T\) 是独立集使得 \(|T| \ge \frac{|S|}{2}\),你发现是 \(\ge \frac{|S|}{2}\),于是容易想到一个奇环的独立集大小是 \(\lfloor \frac{|S|}{2} \rfloor\) 是不合法的,所以存在奇环就不合法,所以补图是一个二分图。
这是充要的,因为对于任何一个集合 \(S\),左右部点一定有一个 \(\ge \frac{|S|}{2}\),所以是合法的,于是得证。
但是边数是 \(O(n^2)\) 太多了怎么办,注意到原图取所有点时至少要一个 \(\ge \frac{n}{2}\) 个点的团,所以 \(m \ge (\frac{n}{2})^2\),于是 \(n \le \sqrt{4m}\),不满足这个限制就直接不合法即可,于是现在补图边数是 \(O(n^2) = O(m)\) 级别的了,直接染色 check 即可。
时间复杂度为 \(O(n + m)\)。

浙公网安备 33010602011771号