2025年2月杂题集

2025年2月杂题集

目录


Part 1

P5904 [POI 2014] HOT-Hotels 加强版

长链剖分与 DP 练习题。首先推出 \(O(n^2)\) 的 DP 式子,由于第二维都与深度有关,所以可以使用长链剖分优化成 \(O(n)\)

对于长链上的儿子直接用指针继承状态,注意要精细实现才能不发生内存混乱。而对于非长链上的儿子则暴力合并。有点类似启发式合并的感觉。

有一些转移式子是枚举两个儿子,需要开一个临时数组记录前缀和优化复杂度。


P10085 [GDKOI2024 提高组] 染色

染一次是这样:

.o.
ooo
.o.

如果再把周围四个方向都染上就会变成:

..o..
.....
o.o.o
.....
..o..

我们把它称作 \(1\) 长十字架。

以此类推,每 \(5\)\(2^x\) 长十字架可以组成一个 \(2^{x+1}\) 长十字架。

注意到如果我们放一个 \(2^{n-1}\) 长十字架,那么左右的就会重合,上下的就会重合,于是就实现了染一个点。

于是我们依次缩小十字架的长度,最后就能知道哪些点染的是 \(0\) 长十字架。复杂度 \(O(2^{2n}n)\)


P1935 [国家集训队] 圈地计划

类比文理分科。变成最小割模型,割完后与 \(S\) 相连则选 \(A\),与 \(T\) 相连则选 \(B\)

注意到这道题是相邻不同有额外贡献,而不是相同,那么我们可以先黑白染色,黑点是左 \(A\)\(B\),白点是左 \(B\)\(A\)
此时额外贡献就很好表示了,还是从 \(S\) 向新增点连一条容量为 \(C\) 的边,从新增点向相邻两个点连容量为 \(inf\) 的边,另一边也同理。
最后答案就是总和减去最小割。


[ARC107F] Sum of Abs

还是最小割模型,不过建模需要仔细斟酌。

最理想情况下,答案应该是 \(-(\sum _{b_i<0} b_i)+\sum_{b_i\ge 0} b_i=\sum|b_i|\),而实际上很难达到理想状态,所以我们可以从理想状态调整建模:

  • 删掉这个点,使答案减少 \(a_i+|b_i|\)
  • 一个 \(b_i<0\) 的点放入取正的连通块,使答案减少 \(-2b_i\)
  • 一个 \(b_i\ge 0\) 的点放入取负的连通块,使答案减少 \(2b_i\)

所以把一个点拆成两个点 \(in_i,out_i\),左右连 \(S\)\(T\),中间连上删点的贡献。

我们还有一个连通块内正负性相同的限制,所以如果 \((u,v)\),那么 \(out_u\to in_v,out_v\to in_u\)


P9878 [EC Final 2021] Check Pattern is Bad

构造题。

Part 1 判断原图是否已经不合法。

Part 2 首先把能确定的都确定了,即把形如

WB
B?

这样的可以直接将问号换成 B

我们正反扫两次就能把这些填完。过程中如果出现填两个颜色都不合法的格子也要输出 NO

Part 3 每次对于剩下的问号,随机填,每填一个就从它开始搜索把能确定的都确定了。注意可能不合法需要回溯,因此要记录搜索时填了哪些位置。


Part 2

CF888G Xor-MST

看到异或首先想到 01-Trie。考虑 Kruscal 的过程,每次找到一条最小的边,看是否能连上。

发现在 01-Trie 上,两点的异或和主要与它们的 LCA 深度有关。

因此我们可以联想到,\(n\) 个点的 01-Trie 恰好有 \(n-1\) 处分叉,即拥有两个儿子的节点。而这些分叉就是答案 MST 的边的端点的 LCA。

现在我们只要对每一个分叉,求出在左右子树中各选一个点,求最小的异或和,可以枚举 Size 较小的一个子树,然后在另一个子树内查询。根据启发式合并的思想,这样枚举是均摊 \(\log\) 级别的,而查询也是 \(\log\) 级别的因此最终复杂度是 \(O(n\log n\log V)\)

我们可以事先对 \(a\) 数组排序,然后在全局的 Trie 上做这些过程,这样就省去了启发式合并 Trie 的过程。


P4098 [HEOI2013] ALO

枚举一个 \(i\),考虑当 \(a_i\) 为次大值时,求异或的最大和。

可以用 ST 表加二分求出前驱最大值和后继最大值,然后我们需要区间查询异或和的最大值,用可持久化 Trie 即可。

时间复杂度 \(O(n(\log n+\log V))\)


P4585 [FJOI2015] 火星商店问题

写起来感觉有一点 shi 的数据结构题。

首先有一个线段树套可持久化 Trie 的做法,对商店开线段树,对时间可持久化,这样时间和空间都是 \(O(n\log ^2n)\),很不优美。

有一个使用线段树分治可以做到时间 \(O(n\log ^2n)\),空间 \(O(n\log n)\) 的做法。

我们把询问的时间区间插到线段树上,于是一件物品就是单点插入,可以用 vector 按商店编号排序,自顶向下更新询问。

01-Trie 则显然就是按商店编号可持久化了。这样做每到一个节点会开一个 Trie,而用完就删掉了,因此空间可以少一个 $\log $。


[AGC023F] 01 on Tree

被称作 Exchange Argument(临项交换)技巧的贪心题。

这道题和之前 abc 的某道 G 题很像。

考虑自顶向下删点很难做,我们可以从独立的 \(n\) 个点开始,每次选择一个点,令它与其父亲连边,表示它的父亲删完以后,立刻删掉它所在的连通块。而每当与 \(0\) 号点(\(1\) 的父亲)连通时就代表执行删除连通块的操作。

而我们需要确定一个连边的顺序,这里用了 Exchange Argument 的 Trick。如果连通块 \(a,b\)\(a_0,b_0\)\(v=0\) 的点,\(a_1,b_1\)\(v=1\) 的点,那么删 \(a\) 比删 \(b\) 更优当且仅当,\(a_1\times b_0<b_1\times a_0\),即

\[\frac {a_1} {a_0} <\frac {b_1} {b_0} \]

于是将 \(\frac {a_1} {a_0}\) 插入优先队列中即可。当 \(a_0=0\) 时根据题意看作无穷大。

每次取出优先队列的 top,然后将其合并到它父亲的连通块,使用并查集维护连通块。

由于还要计算答案,需要在每个连通块维护一个 \(s\) 表示删除连通块内的点的贡献,合并时直接将 \(s\) 相加并且计算额外贡献即可。


P9678 [ICPC 2022 Jinan R] Tree Distance

双倍经验:P9058 [Ynoi2004] rpmtdq

以下 \((i,j)\) 代表 \(dist(i,j)\)

我们把 \((i,j)\) 看做点对 \(i,j\) 的权值,那么原题转化为了二维数点问题,直接做是 \(O((q+n^2)\log n)\)

瓶颈在于点对有 \(O(n^2)\) 个,注意到很多点对是没有用的,实际上有用的点对很少,我们可以找出支配点对

如果点对 \(x,y\)\(a,b\) 满足 \(a\le x\le y\le b\land(x,y)\le (a,b)\)\(a,b\) 显然是没有用的,我们称 \(a,b\)\(x,y\) 支配。
如果点对 \(x,y\) 不被任何另一对点支配,则 \(x,y\) 称作支配点对

我们可以找到一种支配点对的必要条件。将所有可能为支配点对的点对加入集合 \(S\) 并且要使 \(S\) 的大小可接受。

由于是与点对有关的信息,考虑点分治,设当前分治重心为 \(rt\)。我们把当前连通块内任意两点 \(x,y\) 的距离看做 \((x,rt)+(y,rt)\) 即可,因为如果一个支配点对 LCA 不为 \(rt\),则可以在其他分治重心被统计到。

先给出结论:对于 \(x<y<z\)\((x,rt),(y,rt)\le (z,rt)\),点对 \(x,z\) 一定不是支配点对。\(x>y>z\) 也如此。在这里 \(x,z\)\(y,z\) 都在 \(rt\) 的不同子树内,否则可以在其他重心被统计到。证明如下:

\((x,y)\le(x,rt)+(y,rt)\le(x,rt)+(z,rt)=(x,z)\)

所以 \(x,z\)\(x,y\) 支配。

因此只要对 \(x\),将满足 \(y<x\)\((y,rt)\le(x,rt)\) 的最大 \(y\) 与满足 \(y>x\)\((y,rt)\le (x,rt)\) 的最小 \(y\)\(x\) 组成点对加入 \(S\) 即可。

可以将连通块内的点排序后使用单调栈维护。

这样连通块内的每个点都有 \(O(1)\) 个点对,而点分治均摊有 \(O(n\log n)\) 个点,就有 \(O(n\log n)\) 个点对。

剩下的就很简单了,离线后对 \(l\) 扫描线,用树状数组维护 \(r\) 的前缀最小值做二维数点。

时间复杂度 \(O(n\log ^2n+q\log n)\)


Part 3

P4757 [CERC2014] Parades

模拟赛场切的一道题。

由于贪心不可做,所以考虑 DP,首先想设 \(f_x\) 表示子树 \(x\) 内最多选多少条路径。

那么考虑把路径挂在 LCA 上选,对于当前点 \(x\),对于一条路径 \((u,v)\) 满足 \(\text{LCA}(u,v)=x\),选这条路径的贡献就是 \(f_u+f_v+1\) 再加上这条路径上挂着的那些子树的贡献。

除此之外选路径 \((u,v)\) 还要满足 \(x\) 的在 \(u\)\(v\) 方向上的边没有选,于是我们改进状态,加入状态压缩,设 \(f_{x,S}\) 表示选了儿子集合 \(S\) 的答案。

我们可以先用这些路径初始化 \(f\),然后再 \(O(3^{10})\) 枚举子集合并 \(f\)

最后的问题如何算路径的贡献,有了状态压缩的 \(f\) 后就很容易做这个问题,对于 \(x,fa_x\),我们只要把 \(f_{fa_x,U-x}\) 加到 \(x\) 的子树中即可,其中 \(U\) 表示全集。

可以使用树状数组运用差分做子树加、单点查。

时间复杂度 \(O(3^{10}n+(m+n)\log n)\)


P5065 [Ynoi2014] 不归之人与望眼欲穿的人们

模拟赛没做出来的一道分块好题。

首先有一个性质:固定区间左端点后,不同的右端点最多有 \(O(\log V)\) 个不同的或值,其中 \(V\) 是值域。

那么据此可以写出一个 \(O(qn\log V)\) 的做法并得到 70pts。

我们现在要处理出一个数组 \(b_i\) 表示区间长度小于等于 \(i\) 时按位或的最大值是多少。这样查询时即可直接二分。

由于只有 \(O(n\log V)\) 个不同的或值,所以考虑把区间的左端点往右移的过程中,维护出每个不同的或值及其位置。

可以用链表实现,当插入左端点 \(l\) 时,将所有位置或上 \(a_l\),将 \(l\) 作为链表的头,然后对于相同的或值只保留最前面的一个。

每次修改都这样暴力重构。

考虑改进这个做法,瓶颈在于修改时所有位置都扫了一遍太浪费了。考虑分块,设块长为 \(B\)

那么合法的区间分为在一个块中和跨越多个块的情况。

在一个块中

修改时用上面的做法暴力重构一个块,查询时枚举每个块接着做二分,复杂度 \(O(q B\log V)\)

跨越多个块

还是运用上面的性质,一个块内的前缀或后缀只有 \(O(\log V)\) 个不同的或值,那么总共有 \(O(\frac nB\log V)\) 个不同的或值。考虑这样做:

\(pos_i\) 为所在块的编号,\(l_x,r_x\) 为块的左右端点。我们把一个区间 \([L,R]\) 拆成 \([L,l_{pos_R}-1][l_{pos_R},R]\) 分别贡献。

那么我们可以枚举块 \(x\),用以 \(l_x-1\) 结尾的后缀与 \(l_x\) 开头的前缀合并在一起做贡献,由于前者与后者都有最多 \(O(\log V)\) 个或值且都单调,所以可以双指针做。这一部分是 \(O(q\frac n B\log V)\)

后者可以每次暴力重构时处理出一个 \(pre_x\) 数组。

前者可以在从小往大枚举 \(x\) 的过程中,用类似上面的方法来做,每次加入一个块时,加入其中 \(O(\log V)\) 后缀,可以在重构时处理出一个 \(suf_x\) 数组,然后将之前所有值或上这个块的或和,然后将重复元素删去,一样用链表维护。这一部分是 \(O(q\frac n B \log V)\)

而处理 \(pre_x,suf_x\) 都是 \(O(qB\log V)\)

\(B=O(\sqrt n)\) 时可以做到 \(O(q\sqrt n\log V)\)


ARC192C - Range Sums 2

简单交互题,由于 \(p_1<p_2\),我们问出 \(S=q(1,2)\) 后,对于 \(3\le i\le n\),分别问出 \(q(1,i),q(2,i)\)

如果 \(\max(q(1,i),q(2,i))<S\)\(p_1<p_i<p_2\),否则也可以知道在那一侧,然后根据大小关系就可以确定顺序。根据顺序就可以知道 \(a\) 数组。

\(p_1+1=p_2\) 时,可能需要多问一次 \(q(1,k)(p_k=p_1-1)\)\(q(2,k)(p_k=p_2+1)\) 来确定 \(a_{p_1}\)\(a_{p_2}\)


P5279 [ZJOI2019] 麻将

DP 套 DP 练习题,用时 2h10min。

首先我们先建一个能不能判定当前局面是否能胡的自动机,然后在自动机上 DP 即可。在此之前可以先写出判定的 DP 式子然后建自动机。

首先我们只需考虑每种牌的个数。我们先来判定五个面子的情况,设 \(f_{i,j,k,0/1}\) 表示考虑完前 \(i\) 种牌后,当前预留了 \(j\)\((i-1,i)\)\(k\)\(i\),有没有预留对子,值为当前最大的面子数。

注意到到 \(j\ge 3\) 时,可以把三张 \(i-1\) 和三张 \(j-1\) 分别组成两个面子,\(k\ge 3\) 时可以直接组成面子,所以 \(j,k<3\)

于是自动机上的每个点需要记录两个 \(3\times 3\) 的矩阵 \(f_0,f_1\)。另外我们不需要记录 \(i\),因为自动机上并不关心考虑到哪种牌。

另外对于七个对子的情况,只需再在自动机上的每个点记录当前遇到的对子数 \(k\)

那么一个节点胡了当且仅当存在一个 \(f_1\) 中的值大于等于 \(4\),或者 \(k\) 大于等于 \(7\)

实现可以使用 map 里面套两个 \(3\times 3\)vector 和一个 int。注意初始化时只有 \(f_{0,0,0},k=0\),其他设为 \(-1\)。把所有胡的节点当做 \(0\) 号即可。

转移时枚举新增 \(x\) 张牌。有几种如下转移:

  1. \(f_0\) 新增 \(x\) 张牌,转移到 \(f_0'\)
  2. \(f_1\) 新增 \(x\) 张牌,转移到 \(f_1'\)
  3. \(f_0\) 新增 \((x-2)\) 张牌,转移到 \(f_1'\)
  4. \(x\ge 2\)\(k\gets\ k+1\)

转移时再枚举与 \((i-2,i-1)\) 配成面子的张数、与 \(i-1\) 配成 \((i-1,i)\) 的张数、留下 \(i\) 的张数,剩余的拼成尽可能多的面子。

注意 \(f_0\)\(f_1\) 中的值要对 \(4\)\(\min\) 才能保证点数,且 \(-1\) 不能参与转移。

发现算上初始点和胡节点只有 \(2092\) 个点。直接 DP 即可。

我们不要枚举排列,而枚举每种牌选的个数,通过阶乘算出排列的贡献,具体来说设 \(f_{i,j,k}\) 表示考虑完第 \(i\) 种牌后,选了 \(j\) 个额外的牌,走到了自动机的 \(k\) 号节点的方案数。

那么设初始有 \(a_i\)\(i\) 号牌,则转移枚举 \(0\le p\le 4-a_i\),有

\[f_{i-1,j,k}\times \binom {4-a_i} p\to f_{i,j+p,to(k,a_i+p)} \]

最后设 \(g_i\) 为额外选了 \(i\) 张牌后还没有胡的方案数。答案为

\[1+\frac {\sum _{i=1}g_ii!(4n-13-i)!} {(4n-13)!} \]

可以理解为前者是第一张牌,后者是选了 \(i\) 张牌后再选一张的概率。

时间复杂度为 \(2092\times 4\times n^2\)


P4336 [SHOI2016] 黑暗前的幻想乡

容斥+矩阵树定理。

矩阵树定理(无向图)

矩阵树定理用于求一张图的生成树个数(生成树点数等于原图点数)。

定义邻接矩阵 \(A\)\(A_{i,j}\) 表示 \(i,j\) 之间的边数,度数矩阵 \(D\)\(D_{i,i}\) 表示 \(i\) 的度数,拉普拉斯矩阵 \(L=D-A\)

则生成树个数为 \(det(L_{[n]\backslash \{k\},[n]\backslash \{k\}})\),即 \(L\) 除去任意一行与一列后的行列式。

行列式求值

定义如下,其中 \(p\) 为枚举全部排列,\(\sigma (p)\)\(p\) 的逆序对数。

\[det(A)=\sum_p (-1)^{\sigma (p)}\prod A_{i,p_i} \]

直接计算是 \(O(n!)\) 的,但我们可以消元计算做到 \(O(n^3)\)

以下 \(a,b\) 表示两行。

  • 交换 \(a,b\) 行列式取反
  • \(a\gets a\times k\)\(k\) 为常数,行列式不变。
  • \(a\gets a+k\times b\)\(k\) 为常数,行列式不变。

那么我们可以将原矩阵高斯消元成仅 \(A_{i,i}\) 有值的矩阵,此时 \(det(A)=\prod A_{i,i}\)

本题

由于同一种颜色的边不能重复选,所以可以考虑容斥,\(2^{n-1}\) 枚举每种颜色是否选,答案即为

\[\sum_S (-1)^{n-1-|S|}det \]

时间复杂度 \(2^{n-1}(n-2)^3\),当 \(n=17\) 时约为 \(2\times 10^8\)


Part 4

P3317 [SDOI2014] 重建

如果直接套上矩阵树定理,这里度数矩阵即所有边权的和,发现 WA 了,为什么呢?我们考虑一下答案的构成:

答案应该是枚举所有树 \(T\)

\[\sum _T\prod_{i\in E_T} p_i\prod _{i\not\in E_T} (1-p_i) \]

而矩阵树定理根据定义应该是所有可能树的边权乘积的和,即

\[\sum_T\prod _{i\in E_T} p_i \]

那么后面那一坨东西怎么办呢?发现后面可以化成这样:

\[\prod _{i\not\in E_T} (1-p_i)=\dfrac {\prod _{i\in E} (1-p_i)} {\prod _{i\in E_T}(1-p_i)} \]

代入得

\[\prod _{i\in E} (1-p_i) \sum _T \prod _{i\in E_T}\dfrac {p_i} {1-p_i} \]

由于我们用了除法,当 \(p_i=1\) 时就爆炸了,所以当 \(p_i=1\) 时,可以考虑 \(p_i\gets p_i-eps\)

时间复杂度 \(O(n^3)\),比较的 \(eps\) 取了 \(10^{-18}\)\(p_i=1\)\(eps\) 取了 \(10^{-15}\)


P4455 [CQOI2018] 社交网络

矩阵树定理(有向图)

邻接矩阵 \(A_{i,j}\) 表示从 \(i\) 连向 \(j\) 的边数,度数矩阵分为出度矩阵 \(D_{out}\) 和入度矩阵 \(D_{in}\) 两种。

对于外向树(边从根连向叶子方向的树),\(k\) 为根的生成树个数为

\[L=D_{in}-A \]

\[ans=det(L_{[n]\backslash\{k\},[n]\backslash\{k\}}) \]

对于内向树(边从叶子连向根方向的树),\(k\) 为根的生成树个数为

\[L=D_{out}-A \]

\[ans=det(L_{[n]\backslash\{k\},[n]\backslash\{k\}}) \]

本题

直接套用矩阵树定理即可,本题是以 \(1\) 为根的外向树。


P6097 【模板】子集卷积

题意是计算

\[C_i=\sum _{j\lor k=i,j\land k=0} A_jB_k \]

前面 \(j\lor k=i\) 就是 FWT 的或卷积,\(j\land k=0\) 等价于 \(|j|+|k|=|i|\)。可以考虑对每一种 \(popcnt\) 都开一个数组。

即设 \(A_i\to a_{|i|,i},B_i\to b_{|i|,i}\)

那么我们可以计算

\[c_{|i|,i}=\sum _{j=0}^ia_{j}*b_{i-j} \]

其中 \(*\) 表示或卷积。

那么最后答案即 \(C_i=c_{|i|,i}\)

在计算 \(c\) 时,我们计算一下复杂度,如果枚举 \(i,j\)\(O(n2^n)\) 卷积则复杂度为 \(O(n^32^n)\) 无法通过。

但是 FWT 有一个性质,变换后的数组是可加的,即

\[\sum FWT(A)=FWT(\sum A) \]

所以计算出所有 \(a\)\(b\) 在没有经过逆变换时的和,然后再一起逆变换即可,复杂度为 \(O(n^22^n)\)


AT_arc100_c [ARC100E] Or Plus Max

SOS DP。

题意:对于每一个 \(i\) 计算。

\[\max _{j\lor k\le i}a_j+a_k \]

我们可以转而计算对于每个 \(i\) 子集的最大值和次大值,使用 SOS DP 记录最大值和次大值即可。

时间复杂度 \(O(n2^n)\)


AT_abc212_h [ABC212H] Nim Counting

FWT 的可加性、等比数列求和。

算法 1\(n\) 次 FWT 卷积,时间复杂度 \(O(nK\log K)\)

算法 2 由于 FWT 的可加性,我们可以只做一次 FWT 卷积,我们现在就是要对每一项求 \(a+a^2+a^3+\cdots+a^n\)

使用矩阵快速幂写出以下式子可以做到 \(O(K\log K+K\log n)\)

\[\begin{bmatrix} 1 & 1 \\ 0 & a \end{bmatrix} \begin{bmatrix} S \\ a^k \end{bmatrix} = \begin{bmatrix} S+a^k \\ a^{k+1} \end{bmatrix} \]

事实上 \(a+a^2+a^3+\cdots+a^n\) 是等比数列,使用等比数列求和公式:

\(a\) 为首项,\(r\) 为公比,\(n\) 为项数,其中 \(A_1=a,\frac {A_{i+1}}{A_i}=r\)

  • \(r\ne 1\) 时。

    \[\sum _{i=1}^nA_i=a\times\dfrac {r^n-1}{r-1} \]

  • \(r=1\) 时。

    \[\sum_{i=1}^nA_i=a\times n \]

时间复杂度 \(O(K\log K+K\log n)\)


Part 5

jzoj 7366 可怜的木偶 (dance)

由于 \(k!\)\([1,k]\) 所有数的倍数,所以可以先走到 \(0\)。然后要走到最小正整数。

给出结论,如果确定了 \(a\) 数组,则最后最小走到 \(\gcd_{i=1}^na_i\)。证明:

  • 证明答案不小于 \(\gcd\):因为所有数都是 \(\gcd\) 的倍数,且初始时 \(k!\) 也是 \(\gcd\) 的倍数,所以不能走到不为 \(\gcd\) 倍数的位置,则不能小于 \(\gcd\)
  • 证明可以达到 \(\gcd\):考虑前 \(i-1\) 个数的 \(\gcd\)\(d\),现在加入第 \(i\) 个数 \(a_i\),根据裴蜀定理 \(dx+a_iy=\gcd(d,a_i)\) 一定有整数解,即可以通过走若干次 \(d\)\(a_i\) 走到 \(\gcd(d,a_i)\),因此 \(n\) 个数可以走到 \(\gcd_{i=1}^na_i\)

考虑设 \(f(x)\) 表示 \(\gcd\)\(x\) 的方案数。设 \(g(x)\) 为所有 \(\gcd\)\(x\) 的倍数的方案数的总和,则

\[g(x)=\lfloor\frac k x\rfloor^n=\sum_{x|d} f(d) \]

根据莫比乌斯反演,

\[f(x)=\sum_{x|d} \mu(d)\times g(\frac d x) \]

最后的答案即为

\[\frac {\sum _{i=1}^ki\times f(i)}{k^n} \]

根据实现可以做到 \(O(Tk\log k)\)\(O(k\log n+Tk)\),足以通过此题。

更优的复杂度

展开得

\[\sum_{x=1}^kx\sum_{x|d}\mu(\frac d x)\times \lfloor\frac k d\rfloor^n \]

枚举 \(y=\frac d x\)

\[\sum_{x=1}^kx\sum_{y=1}^{\lfloor\frac kx\rfloor}\mu(y)\times \lfloor \frac k{xy}\rfloor^n \]

枚举 \(xy\)

\[\sum_{i=1}^k\sum_{j|i}j\times \mu(\frac ij)\times\lfloor\frac ki\rfloor^n \]

根据狄利克雷卷积 \(\sum _{j|i}j\times \mu(\frac i j)=\varphi(i)\)。因此答案为

\[\frac {\sum_{i=1}^k\lfloor\frac k i\rfloor^n\varphi(i)}{k^n} \]

套上数论分块可以做到 \(O(k\log n+T\sqrt k)\)


SP11470 TTM - To the moon

区间加的可持久化线段树。

调了很久终于发现了问题所在:由于用了标记永久化,标记不下传,因此不能从两个子树合并贡献,需要在修改下传时在每个节点加上贡献。

void update(int &x,int y,int l,int r,int L,int R,int z){
	if(!x) x=++tot,ls[x]=ls[y],rs[x]=rs[y],tag[x]=tag[y],s[x]=s[y];
	s[x]+=(ll)(min(R,r)-max(L,l)+1)*z;
	if(L<=l&&r<=R) {
		tag[x]+=z;
		return;
	}
	if(L<=mid) {
		if(ls[x]==ls[y]) ls[x]=0;
		update(ls[x],ls[y],l,mid,L,R,z);
	}
	if(R>mid) {
		if(rs[x]==rs[y]) rs[x]=0;
		update(rs[x],rs[y],mid+1,r,L,R,z);
	}
}

其中第三行 s[x]+=(ll)(min(R,r)-max(L,l)+1)*z; 很重要,并且最后不应该 s[x]=s[ls[x]]+s[rs[x]]


AtCoder WTF2019 A

考虑到每次把 \(1\sim n\) 扫一次 \(K\) 就会减 \(1\),每次 \(K\)\(1\) 我们称作一轮。

我们应该要做 \(K+1\) 轮就必定能找到宝藏。

考虑到 \(1\sim n\) 扫完后,最后一个开的盒子 \(x\) 一定没有宝藏,于是下一轮就可以不用扫 \(x\)

也就是对于除了第一轮的每一轮,我们可以选择一个盒子不用开,因为这个盒子在上一轮的最后开过了。

那么令 \(b\) 为上一轮最后开的盒子,找到 \(nx\) 为满足与 \(b\) 不等且使 \(a_{nx}\) 最小的位置,那么扫一遍所有满足 \(i\ne nx\)\(i\ne b\) 的盒子,最后再开 \(nx\),然后 \(b\gets nx\)

每次开一个盒子时让 \(a_i\gets a_i-1\)

当存在 \(a_i<0\) 时无解,否则一共开了 \(n(K+1)-K\) 次盒子。时间复杂度 \(O(nK)\)


AT_awtf2024_d Almost Bubble Sort

相当于选一个下标集合 \(S\),使得 \(S\) 内元素 \(+n\),然后统计逆序对个数。

发现它又等于 \(inv(\{1\dots n\}\backslash S)+inv(S)+(\sum _{i\in S} n-i)-\binom {|S|}2\)。其中 \(inv(S)\) 表示子序列 \(S\) 的逆序对个数。即 \(S\) 的逆序对个数加上除去 \(S\) 的逆序对个数再加上对一个 \(01\) 排序的交换次数。

如果考虑把 \(n\) 个点表示成平面上的 \((i,p_i)\),那么发现最优选 \(S\) 的方案一定形如有一条从左下角开始的向右向上的折线,使得折线下方都 \(+n\)

由于最后有一个关于 \(|S|\) 的贡献,所以如果直接 DP 并不好做。考虑设 \(c1_i\) 表示 \(i\) 左上方的点数,\(c2_i\) 表示 \(i\) 右下方的点数,那么选 \(S\) 就会贡献 \(c2_i+n-i\),并且最后的最后要加上 \(\binom {|S|}2\),而不选 \(S\) 就会贡献 \(c1_i\)

我们可以初始让所有点都不选 \(S\),然后每次选一个点让它 \(+n\),那么选一个点的贡献为 \(f_i=c2_i-c1_i+n-i\)。那么对 \(f\) 排序后按顺序选即可,这种方式也能方便贡献 \(\binom {|S|} 2\),时间复杂度 \(O(n\log n)\)


P7771 【模板】欧拉路径

欧拉路径:一个图中经过每条边恰好一次的路径,允许经过重复点。

欧拉回路:起点与终点相同的欧拉路径。

对于连通图,欧拉路径有如下判定:

  1. 对于无向图,恰好有两个点度数为奇数时,存在起点与终点不同的欧拉路径,且起点与终点就是这两个奇度数的点。
  2. 对于无向图,所有点度数均为偶数时,存在欧拉回路。
  3. 对于有向图,存在一个点 \(x\) 满足 \(deg_{out}+1=deg_{in}\),且存在一个点 \(y\) 满足 \(deg_{in}+1=deg_{out}\),且其他点入度等于出度,则存在起点与终点不同的欧拉路径,且 \(x\) 是起点,\(y\) 是终点。
  4. 对于有向图,所有点入度等于出度,存在欧拉回路。

寻找欧拉路径

基本思想:定义递归函数 \(dfs(x)\) 返回一个 \(x\) 的环,过程如下,先找到一个 \(x\) 的环 \(T\) 使得每条边都没有被走过,然后对于环上的每一个点 \(y\),将 \(dfs(y)\) 返回的环插入 \(T\) 中。

算法实际上不太一样,对于 \(dfs(x)\)

  1. 首先遍历每条未走过的出边(可能之前调用过 \(x\) 导致一些出边已走过)到 \(v\)
  2. 调用 \(dfs(v)\)
  3. 当所有出边都遍历完后,将 \(x\) 加入答案序列。

最后倒序输出答案序列即题目所需的答案。

本题还要求字典序最小,因此需要将出边排序,用 vector 记录出边。

实现上对于每一个点 \(x\) 记录 \(cur_x\) 表示当前弧,因为一个递归树中可能出现标号为 \(x\) 的点的子树内又出现了标号为 \(x\) 的点。


Part 6

P6628 [省选联考 2020 B 卷] 丁香之路

考虑题目要求的路径就是从 \(s\) 开始 \(i\) 结束的欧拉路径。我们先插入一条边 \((s,i)\) 把题目变成欧拉回路。

那么接下来就是要用最少的边权使原图变为合法的欧拉回路。

我们从 \(1\sim n\) 遍历 \(i\),如果 \(i\) 的度数为奇数,则连一条 \((i,i+1)\),发现这样连边是最优的,比把相邻度数为奇数的点相连更优,因为这样连边还可以使得图尽可能连通。

但图还有可能不连通,考虑把有边的点对用并查集缩点,相邻的点之间建边,然后跑最小生成树,发现欧拉回路的答案就会加上两倍最小生成树的权值。

时间复杂度 \(O(m+n^2+n\log n)\)。给定的 \(m\) 条边要预处理,因为如果每个 \(i\) 都枚举这 \(m\) 条边,复杂度将变成 \(O(nm+n\log n)\)


AT_agc018_f [AGC018F] Two Trees

很厉害的结论题。

由于 \(-1\)\(1\) 的奇偶性相同,如果一个编号在左树和右树中儿子个数的奇偶性不同就是无解。

否则我们可以这样构造:
先将两棵树的根连向一个超级根,那么现在所有节点都等价了。
对于度数为奇数的点,我们将它们在两棵树上的点连起来。
那么现在所有点都是偶数度数,我们跑出欧拉回路。
对于原本是偶数度数的点,\(X=0\)
对于原本是奇数度数的点,如果额外的那一条边在回路上是从左走到右,那么 \(X=1\),否则 \(X=-1\)

证明:对于树上一个点,欧拉路径进出其子树偶数次,其中一次经过其与其父亲的连边,剩余奇数次进出其子树内的额外边,且进入和出去的次数恰好相差 \(1\),那么因为进出的边权为 \(\pm 1\),所以这个点的子树和就是 \(\pm1\)


ARC193B Broken Wheel

因为 \(\sum d\) 是一定的,所以确定了 \((d_0,d_1,\dots d_{n-1})\) 就能确定 \(d_n\),所以考虑计算它。

显然一种 \(d\) 序列可能对应多种连边方式。我们可以设 \(f_{i,0/1/2}\) 分别表示 \((i-1,i)\) 一定选连右、一定选连左、连左右均可的 \((d_{0},d_{1},\dots,d_{i-1})\) 方案数,这里的「连左右均可」计算的是满足连左或连右都可以被构造出的 \((d_0,d_1,\dots,d_{i-1})\)

我们根据 \(s_{i-1}\) 的值讨论每一种可能的 \(d_{i-1}\) 即可转移。

那么我们指定 \((n-1,0)\) 连的是什么边,对应以下初始化与需要加上的值:

  • \(f_{0,0}=1,f_{0,1}=f_{0,2}=0\),计算 \(f_{n,0}\)
  • \(f_{0,1}=1,f_{0,0}=f_{0,2}=0\),计算 \(f_{n,1}\)
  • \(f_{0,2}=1,f_{0,0}=f_{0,1}=0\),计算 \(f_{n,2}\)

以上,发现会算重的情况当且仅当 \((d_0,d_1,\dots,d_{n-1})=(1,1,\dots,1)\),且 \((n-1,0)\)\(0/1/2\) 都会被算一次。

所以最后将答案减 \(2\) 输出即可。


P8528 [Ynoi2003] 铃原露露

考虑对于 \((x,y,z=\text{lca}(x,y))\),如果 \(a_x<a_z< a_y\) 那么不会对不合法区间造成贡献,否则:

  • \(a_z<a_x<a_y\),则对于 \(l\in(a_z,a_x],r\ge a_y\) 的区间不合法。
  • \(a_x<a_y<a_z\),则对于 \(l\le a_x,r\in[a_y,a_z)\) 的区间不合法。

可以想到一个树上启发式合并的过程,维护每个点子树内 \(a\) 集合,当 \(x,y\)\(z\) 处合并时,插入不合法的区间。

由于不合法的区间是包含 \(x,y\) 而不包含 \(z\),所以当 \(x\) 合并到 \(S\) 集合中时,只要查找 \(a_x\)\(S\) 中的前驱与后继即可。

每次合并一个节点产生 \(O(1)\) 个支配对,所以支配点对的数量是 \(O(n\log n)\)

接下来的问题形如给一个矩形加,然后查询矩形内为 \(0\) 的位置个数。

扫描线以后,就是区间加,差分后查询区间为 \(0\) 的个数的历史和。使用线段树维护。

具体来说,我们维护维护区间最小值、最小值的个数、\(0\) 的个数的历史和。

标记需要维护加标记、历史标记。历史标记表示区间内最小值会对历史和贡献多少次。

下传历史标记时需要知道哪些子区间是原先的最小值,因此上传时需要记录区间最值由哪些子区间转移而来。

每次如果全局的最小值为 \(0\),则对树根的历史标记加 \(1\)

时间复杂度 \(O(n\log ^2n+q\log n)\)


P9166 [省选联考 2023] 火车站

对于一条轨道 \(l,r\),我们 \(\forall i\in[l,r)\) 连无向边 \((i,i+1)\)。则只需统计与 \(x\) 连通的点即可。

由于轨道之间是没有区别的,所以可以差分实现区间加 \(1\),当 \(s_i>0\) 时表示 \((i,i+1)\) 之间有一条边。

查询则从 \(x\) 开始往左和往右走,往左只统计左端点,往右只统计右端点。时间复杂度 \(O(n)\)


Part 7

P2391 白雪皑皑

由于后来的区间会覆盖之前的区间,我们考虑倒着做,那么每次就要覆盖区间内的 \(0\)

考虑并查集维护一个点后继的 \(0\),时间复杂度 \(O(n \alpha(n))\)

posted @ 2025-02-11 16:29  dengchengyu  阅读(81)  评论(0)    收藏  举报