2025.1

2025.1

ARC101E

不会直接算,容斥。我们考虑钦定一些边不覆盖,这样整棵树变为一些个连通块。

\[f(S) = \sum (-1) ^ {|S|} \prod_{x\in S} g(x) \]

这个式子中, \(|S|\) 是连通块的集合, \(x\) 是其中的一个连通块。 \(g(x)\) 显然为 \((|x| - 1) \times (|x| - 3) \times \cdots \times 3 \times 1\) ,先预处理出来。

我们再考虑上面的东西怎么算。我们发现 \(g(x)\) 只与 \(|x|\) 有关,我们设 \(f(x, i)\) 表示以 \(x\) 为根的子树的答案。其中 \(i\) 表示 \(x\) 所在的连通块大小为 \(i\)

考虑一条边 \(x \to y\) ,我们可以将两个连通块合并,也可以分开算贡献。

  1. 合并两个连通块:

\[f(x, i + j) = f(x, i) \times f(y, j) \]

  1. 分开算贡献,把容斥带进去算。就是给新的 \(f(y, j)\) 带上 -1 的容斥系数。因为在后面的计算中 \(y\) 对答案的贡献和 \(x\) 对答案的贡献相反。

\[f(x, i) = f(x, i) - f(x, i) \times f(y, j) \times g(j) \]

由于以 1 为根的贡献我们没有计算,所以答案是 \(\sum f(1, i) \times g(i)\)

P4859

先令新的 \(k\) 变为 \(\frac{k + n}{2}\) ,现在 \(k\) 的意思变为 \(a(i) > b(i)\) 的个数。

钦定\(k\)\(a(i) > b(i)\) 然后剩下乱填,记为 \(g(k)\) ,最后答案就是 \(\sum(-1) ^ {i - k}\binom{i}{k} g(i)\)

现在考虑如何计算 \(g(i)\) 。我们可以设 \(f(i, j)\) 表示前 \(i\) 个数让 \(j\) 个钦定满足,容易写出状态转移方程:

\[f(u, j) = f(i - 1, j) + f(i - 1, j - 1) \times (pos(i) - j + 1) \]

其中 \(pos(i) - j + 1\)\(i\) 填的位置的方案数。 \(g(i) = f(n, i) \times (n - i) !\)

然后就做完了。

P4463

\(f(i, j)\) 表示选了 \(i\)\(\le j\) 数的所有不合法序列的值之和。容易列出:

\[f(i, j) = f(i, j - 1) + f(i - 1, j - 1) \times j \]

我们发现这个式子是若干次前缀和相加。我们猜想这个 \(f(i, *)\) 是一个关于 \(j\) 的多项式。

使用拉格朗日插值可以快速解决这个问题。现在我们只需找到这个多项式的项数就好了。

我们知道如果 \(A(x)\)\(n\) 次多项式,那么 \(A(x) - A(x - 1)\)\(n - 1\) 次多项式。

转化一下上面的式子,我们发现 \(f(i, j) - f(i, j - 1) = f(i - 1, j - 1) \times j\)

可以发现 \(f(i, *)\)\(2n\) 次多项式。然后暴力转移前 \(2n +1\) 项然后拉格朗日插值就好了。

AGC030D

计数转期望然后乘 \(2^q\) 。假设每次随机交换,直接设 \(f(x, y)\)\(a(x) < a(y)\) 的概率。然后每次交换两个数都相当与把两个数变为平均数。

同时的,对于 \(f(x, i) , f(y, i)\)\(f(i, x) , f(i, y)\) 也要取平均。

qoj 7502

\(O(n^2)\) 想树形背包。我们发现这道题让我们强制钦定一些边走 奇/偶数 次,并且要区分入边和出边。

我们不如让子树 \(x\) 中连向 \(x\) 的入边贡献 1 ,出边贡献 -1 ,这样我们直接将两个贡献相加,能直接算出还剩多少条入边或出边,并且我们同时能很好满足钦定经过奇数次或偶数次的限制。

具体的,我们设 \(f(x, i)\) 表示以 \(x\) 为根,入边数 - 出边数为 \(i\) 的最小贡献。容易写出:

\[f(x, i + j) = min\{ f(x, i) + f(y, j) + |j| \times w(x \to y)\} \]

平移数组直接转移可以做到 \(O(n ^ 2)\) 。本题实现有点小细节,每个点 \(x\)\(f(x, i)\) 有意义当且仅当 \(-s(x)\le i \le sum(x)\) 。其中 \(s(x)\) 是子树大小, \(sum(x)\) 是子树中可以出发的点的个数。

模拟赛 T2

先用类似标记永久化的东西把每个守望者挂到每个线段树的叶子上。然后每次查询对 \(O(\log n)\) 个答案取最大值。

现在我们只用考虑线段树上每个叶子怎么做。容易发现,我们要求的是对于时间的一串后缀的历史最大值。历史最值用 Segment Tree Beats 类似的操作维护。

对时间维护一条链,我们对每个新加进来的询问新加一个点,每次修改只在最后一个点修改。查询时查询一条链上的信息。

使用并查集路径压缩解决这个问题,时间复杂度为 \(O(n \log ^ 2 n)\)

ARC144D

先转化式子,变为 \(a(S) + a(T) - a(S \cap T) = a(S \cup T)\)

我们考虑几个相互独立的 \(S\) ,发现只要确定 \(a(2^0), a(2^1), a(2^2) ,\dots , a(2^{n - 1})\) ,剩下的都可以被算出来。同时,我们还可以给 \(a(1 \sim 2^{n - 1})\) 的数加上一个偏移量 \(a(0)\) ,上式仍然满足。

我们最后的方案数就是我们乱填 \(a(2^i)\)的情况乘上确定 \(a(2^i)\)\(a(0)\) 的取值情况。

先设 \(S = \{a(2^i)\}\)\(a(S) = a(0) + \sum_{x\in S}a(x)\) 。所以 \(a(0)\) 的取值范围为 \([\sum_{x \in S , x < 0} x, k - \sum_{x \in S , x > 0}]\) 。总情况数 \(k + 1 - \sum_{x\in S} |x|\)

每个不为 0 的 \(x\) 对答案的贡献为 2 , 0 对答案的贡献为 1 。

枚举现在有 \(i\) 个非 0 的位置,乱填 \(a(2^i)\) 的情况为 \(\binom{n}{i} 2^i\) 。(先从 \(n\) 个数中选出 \(i\) 个数,每个数有正有负两种情况)

现在考虑 \(k + 1 - \sum_{x\in S} |x|\) ,的情况,相当于将 \(k + 1\) 个数中一段位置 \(t\) 给前 \(i\) 个数划分,贡献为 \(\binom{t - 1}{i - 1}\) ,剩下的 \(k + 1 - t\) 表示 \(a(0)\) 的取值情况。显然,我们可以新加一个划分的位置留给 \(a(0)\) ,总的贡献为 \(\binom{k + 1}{i + 1}\)

所以答案就是:

\[\sum_{i = 0} ^n \binom{n}{i} 2^i \binom{k + 1}{i + 1} \]

P10240

有两个限制,首先要物品数量最多,其次要字典序最大。

先用 set 维护出当前要删几个。然后目前要选一个能满足物品数量的同时编号最大的。这启发我们在元原序列上二分,这时能选择的元素是一个前缀。

我们找这个前缀中前 \(k\) 小的元素,判断合法性。这样我们就能二分出最大我们能填什么。

具体的,我们判断合法性可以在一个动态开点的权值线段树上二分出前 \(k\) 大的元素是什么。

同时,我们还要动态删除元素,所以我们可以在外面套一个树状数组,只在 \(O(\log n)\) 棵线段树上修改。

二分 + 树状数组 + 动态开点的权值线段树,总的时间复杂度为 \(O(n \log ^ 3 n)\)\(n\) 只有 50000 ,所以可以通过。

qoj 8574

一个特例,当 \(k = 2\) 时是冒泡排序,答案为 \(0\) 。我们推广一下发现当 \(k\) 为偶数时且 \(n\ne k\) 时答案一定为 0 。

\(k = 4\) 时,我们可以选 \(5\) 个数手玩一下:

\[(A,B,C,D,E) \to (C,D,A,B,E) \to (D,A,E,B,C) \to(B,A,C,D,E) \]

大概逻辑是先把 \(A,B\) 都移开,在分别把 \(A,B\) 放在对应的位置。这样就等价与 \(k = 2\) 。对于 \(k\) 为其他不为 \(n\) 的偶数时都成立。

\(k = 1\) 时,直接贪心模拟即可。当 \(k = n\) 时,直接 \(O(nk)\) 枚举所有情况然后沿用 \(k = 1\) 的做法即可。

最后考虑 \(k\) 为奇数的情况,我们先尽可能解决一些逆序对。继续手玩发现:

\[(A, B, C, D) \to (B, C, A, D) \to (B, A, D, C) \]

这里 \(k = 3\) ,发现我们可以交换两个位置的逆序对。所以如果逆序对数为奇数,那么答案就是对 \(a(i)\) 排序后的 \(\min \{a(i + 1) - a(i)\}\) ,如果逆序对数为偶数,那么答案为 \(0\)

ABC255G

考虑 \(SG(x)\) 的取值。我们发现每一个特殊限制都会导致 \(SG(x)\) 突变。

对于每个游戏,都有 \(SG(x) = \text{mex}_{i < x}{SG(i)}\) 。对于每个限制 \(x_i, y_i\) 。我们直接在 \(SG(x_i)\) 中删除 \(SG(x_i - y_i)\)

再发现,如果没有突变点, \(SG(x)\) 是一条斜率为 1 的直线。我们每次二分找到这个位置即可。

P5406

最大化边权没法做。我们可以直接算出权值为 \(k\) 时的答案。由于 \(n \le 70\) ,所以我们考虑矩阵树定理计数。

矩阵树定理本质上在求 \(\sum_T \prod_{e \in T} w(e)\) 。我们可以把边换为多项式。然后边和边之间用 \(FWT\) 算,这样就能求出每个答案是否合法。

所以我们先对边权 \(FWT\) ,计算矩阵的行列式,再把行列式的结果 \(IFWT\) 回来,这样就算完了。

P7450

先把问题拆开,先保证选取的块数最少,然后在此基础上找到中位数。

我们可以用 微小扰动 解决。我们二分这个中位数是什么。大于 \(mid\) 加上 \(eps\) ,反之减去 \(eps\) 。二分让扰动后的答案和原来的答案相等,最后的答案就是二分的终止位置。

再考虑如何让选取的块最少。我们设 \(f(i, j, S)\) 表示当前位置为 \(i, j\) ,颜色的集合为 \(S\)

我们可以列出方程使用斯坦纳树解决:

\[f(i', j', S) = f(i, j, S) + w(i, j) \]

\[f(i, j, S) = f(i, j, T) + f(i, j, S \oplus T) - w(i, j) \]

但是这样只能解决 $a(i, j) $ 比较小的情况。当元素比较多时,我们可以把它们映射到 \([0, k)\) 中,这样每次正确判断的概率为 \(\frac{k!}{k ^ k}\)

多随机几次就能保证正确性。这个东西叫做 color-coding

CF1037H

要查询一个子串在 \(s[L...R]\) 是否出现可以使用 \(SAM\) 维护 \(endpos\) 等价类实现。

对于 \(SAM\) 上的每个点,我们给它插入 \(len(i)\) ,对于 fail 树上的边,我们线段树合并子树信息就能得知所有点 \(i\)\(endpos\) 等价类。

对于这道题,我们暴力匹配尽可能长的前缀,然后枚举下一位填什么然后后面不填,用 \(endpos\) 等价类判断这个字符串是否在 \([L, R]\) 中出现。

qoj 7884

先发现选一个没有什么限制的连通块不是最优的。因为每个连通块只有最大值和次大值是有用的。所以我们可以让连通块缩小为一条从最大值到次大值的链,这样做一定是不劣的。

然后我们就能设计 dp 状态,我们维护 \(x\) 连出去的链。 \(f(x)\) 表示以 \(x\) 为根的答案, \(g(x, k)\) 表示当 \(x\) 连出去的链的另一端为 \(k\) 的答案。枚举儿子节点 \(y\) ,转移是容易的。

\[f(x) = \max \{f(x) + f(y), g(x, j) + g(y, k) + \min(j, k)\} \]

\[f(x, k) = \max \{f(x, k) + \sum g(y') , f(y, k) + \sum_{y' \ne y} g(y')\} \]

可以线段树合并维护上面的式子。具体来说,我们可以维护当前的 \(\sum g(y')\)\(\sum_{y' \ne y} g(y')\) ,每次合并时算出当前的值取 max 更新 \(g(x)\)

qoj 9682

通过博弈论的性质,我们就是要进行若干次给某个位置加 1 的操作让所有的数异或和为 0 。

容易想到从大往小按位贪心,先满足前面的位数异或和为 0 。

假设我们现在在操作第 \(k\) 位,我们现在考虑位置 \(x\) 的数加多少。先算出不操作时异或和是多少,我们通过调整让最后的异或和为 0 。

假设我们要让当前位异或上 1 ,我们可以选择一个第 \(k\) 位为 0 的数,通过若干次操作让这一位变为 1 。

我们还可以找到两个第 k 位为 1 的数,让它们在前 \(k - 1\) 位改变相同的位置,然后将其中一个数的第 \(k\) 位变为 0 。

我们所有的情况都能通过上面的方式异或出来。但是如果直接暴搜时间复杂度会出问题。

我们考虑一步贪心,我们如果先操作对答案贡献较小的数,那么符合条件的位置就是一段前缀,后面不用考虑。

这样再去搜索时间复杂度就会和 \(m\)\(\min\) ,复杂度瓶颈在于对于每一位给 \(a(x)\) 排序,总的时间复杂度为 \(O(n\log n \log V)\)

P6054

考虑最大流最小割定理,我们将每个选手抽象为一条链。容易发现,在这条链中有且仅有一条边被删。

我们可以把限制抽象为 \(x_i < y_i + D\) 的形式。构建一些新的链满足这个限制。

我们记 \((x, i)\) 为链 \(x\) 上的第 \(i\) 个点,我们构造一条链 \(S \to (y, i + D) \to (x, i) \to T\) ,即连边 \((y, i + D) \to (x, i)\) ,为避免隔断设流量为 \(+\inf\)

如果我们选择了 \(S \to (y, i + D)\) 上的边,那么由最小割的性质, \((x, i) \to T\) 上的边就一定不会被选择,所以只会选择 \(S\to (x, i - 1)\) 上的点,相当于满足限制 \(x_i < y_i + D\)

考虑边界情况,如果 \(D\) 为正数,那么对于 \(i + D > m\) 的点,\(x\) 可以任意取值不影响答案。但对于 \(D\) 为负数的点,当 \(y_i\) 选择的位置 \(i + D > m\) 时,\(x\) 没有位置可以选,这种情况不合法,我们考虑把这种情况去掉。

我们可以对于每条链 \(S \to (x, i) \to T\) 连一条反链 \(T \to (x, i) \to S\) 流量全部设置为 \(+\inf\) 。这样就能保证不合法的点不被选,因为还能选出一条增广路不满足条件。

这就是 广义切糕模型 ,对于这道题 \(D\) 为负数,所以我们按第二种情况建出网络流求解即可。

qoj 2441

首先选出的若干堆式子肯定构成一组线性基,否则我们可以通过线性基构造出一个数然后异或和为 0 。

现在我们需要维护如何快速处理这些信息。我们可以贪心插入每个元素,如果当前元素可以使得和更大,那么我们贪心替换这个元素。

我们还需要快速处理后缀信息,可以使用 \(SAM\) 来维护。我们统计每个点出现了多少次,就处理出这个点往后到达几个终止节点的路径数。

对于一个区间 \([l,r]\) ,我们从 \(r\) 往前倍增跳 \(father\) 即可,时间复杂度为 \(O(n \log n \log V)\)

uoj 938

首先最后每个树上的点都对应了原树上的某个连通块。我们可以处理出一些子树信息合并两个答案。

我们设 \(f(x)\) 是把以 \(x\) 为根的子树变为满二叉树后的树高, \(g(x)\) 是把除 \(x\) 以外的树变为满二叉树的树高。

合并是几乎一样的。对于每个节点 \(x\) ,我们考虑两个高度相同的子节点 \(f(y)\) ,如果两者相等,那么 \(f(x) = f(y) + 1\) ,否则转移就是 \(f(x) = \max_{y \in son(x)} f(y)\)。可以用各种 STL 快速合并答案。

posted @ 2025-01-05 14:20  lichenyu_ac  阅读(35)  评论(0)    收藏  举报