2025-07-11 总结

2025-07-11 总结

小R的旅行

Tag:点分治、倍增。

考虑从 \(u\) 走到 \(v\) 过程中,每条边的花费即此前 \(p_i\) 的最小值。那么对于链的情况,可以找到一个点往上或往下第一个 \(p_i\) 比它小的点,查询时用倍增跳即可。

现在考虑树,从 \(u\) 走到 LCA 依然可以类似链的做法,但从 LCA 走到 \(v\) 是不好做的。

考虑点分治,把询问挂在路径上的最浅重心上,那么我们可以预处理重心到子树内每个点的答案,然而不能直接合并。我们需要先知道从 \(u\) 到重心时 \(p_i\) 的最小值 \(Min\),然后根据这个最小值从 \(v\) 倍增跳到 \(x\),使得重心到 \(x\) 的花费大于 \(Min\),而 \(x,v\) 的花费不大于 \(Min\),从而算出答案。

考虑复杂度 \(T(n)=2T(n/2)+O(n\log n)=O(n\log ^2n)\)

数数

Tag:组合数学、二项式反演、斯特林数。

首先假设 \(a_i\) 互不相同,在最后除以每种 \(a_i\) 出现次数的阶乘的乘积即可。

考虑计算划分成至少 \(k\) 个和为 0 的集合并排列的方案数 \(h_i\times i!\)。由二项式反演,那么答案为 \(ans_i=\sum _{j=i}^n(-1)^{j-i}\binom{j-1}{i-1}h_i\times i!\),这里因为最后一个集合的和一定为 \(0\) 所以系数为 \(\binom{i-1}{j-1}\)

对于 \(cnt\) 个和为 \(s\) 的非 \(-1\) 数若划分进一个集合,方案数为 \((cnt+1)(cnt+2)\cdots(cnt+s)\)。若这 \(cnt\) 个数分别为 \(b_1,b_2,\dots,b_{cnt}\),那么考虑其组合意义,我们为每一个 \(i\) 任选一个 \(j\) 并令 \(c_i=b_j+[j\le i]\),则方案数为所有选 \(j\) 的方案中 \(\prod c_i\) 的和。

为一个 \(i\)\(j\) 看做 \(i\)\(j\) 连一条有向边,那么一个集合可能分成若干基环树。设 \(g_i\) 为将 \(n\) 个点分成 \(i\) 个基环树的方案数,其中一条边的贡献为 \(c_i\)。则 \(h_i=\sum _{j=i}^ng_i\times S_2(j,i)\),其中 \(S_2\) 为第二类斯特林数。

为了算 \(g_i\),考虑求出至少分成 \(i\) 个基环树的方案数 \(f_i\),那么由二项式反演 \(g_i=\sum_{j=i}^{n} (-1)^{j-i}\binom{j}{i}f_i\)

\(f_i\),即确定 \(i\) 个环,剩下的点随便选,一个点随便选的方案数是 \(i+\sum a\)

考虑一条环边 \((i,j)\),我们把贡献记作 \((b_j+1)-[j>i]\),那么它们相乘后的组合意义即,每个点 \(i\) 可以选择 \(a_i+1\) 的贡献或 \(-1\) 的贡献,其中 \(-1\) 的贡献只有当前一个点小于它时可以选。那么把环分割成若干链,其中链首的贡献为 \(a_i+1\),其余点的贡献为 \(-1\),并且要保证一条链上点编号递增。考虑求 \(dp_{i,j}\) 表示 \(i\) 个点分割成 \(j\) 条链的方案数。

那么对于一个点可以随便连,贡献为 \(i+\sum a\);可以作为链首,贡献为 \(a_i+1\);可以拼到一个链以后贡献为 \(-1\),并可以选择一个链拼,所以总贡献为 \(-j\)

于是 \(dp_{i,j}=(i+\sum a)dp_{i-1,j}+(a_i+1)dp_{i-1,j-1}-j\times dp_{i-1,j}\)

算出拼成 \(i\) 条链的方案数后,还要把 \(i\) 条链拼成环。则 \(f_i=\sum _{j=i}^ndp_{n,j}\times S_1(j,i)\),其中 \(S_1\) 为第一类斯特林数。

从后往前依次带入算式即可得出答案,复杂度 \(O(n^2)\)

图排列

Tag:分治、偏序。

首先 \(n\) 个点的图是竞赛图,子图也是竞赛图。对于一个竞赛图,它的强连通分量会连成一个类似链的结构,其中链每对祖孙都有一条边,即构成一个全序关系。

现在考虑加入一个点,在从左往右的链上,如果找到最左被它连向的点 \(x\),和最右连向它的点 \(y\),那么 \(x,y\) 所在分量之间和它就会合并成一个强连通分量。我们可以预处理好所有点的 \(x,y\),然后维护这条链,使用链表将 \(x,y\) 分量之间的点缩起来,还需要维护一个并查集用于求出 \(x,y\) 所在的分量。

现在问题在于求出 \(x,y\)。考虑求 \(x\)\(y\) 是同理的。我们实现如下函数:

int Min(int x,int y) {
    return (!x||!y)?(x|y):(x<y?(a[x]>b[y]?x:y):(a[y]>b[x]?y:x));
}

\(x\to y\) 当且仅当 \(Min(x,y)=x\)

我们现在求出 \(p_i\) 的最左被它连向的点,发现对于 \(j<i,k<i\)\(Min(p_i,p_j)=Min(p_i,p_k)=p_i\)\(p_j,p_k\),若 \(Min(p_j,p_k)=p_j\),则 \(p_j\)\(p_k\) 左边或与 \(p_k\) 在同一个连通块,\(p_j\) 更优。

所以对于 \(p_i\) 我们要求的点 \(p_j\) 有这几个条件:\(j<i\)\(Min(p_i,p_j)=p_i\)\(p_j\) 为满足以上两个条件的点集的 \(Min\)

于是对 \(p_1,p_2,\dots,p_n\) 分治,每次用 \(p_{l}\sim p_{mid}\) 更新 \(p_{mid+1}\sim p_{r}\)。对于第二个条件可以讨论成二维偏序,对于第三个条件就是放在树状数组上求 \(Min\)

复杂度 \(O(n\log ^2n)\)

posted @ 2025-07-12 10:42  dengchengyu  阅读(31)  评论(0)    收藏  举报