2026.3/ 2026.4 杂题

AT_abc290_f [ABC290F] Maximum Diameter

考虑一个 \(X\),其最长直径是多少。不难发现就是 \(\sum_{i=1}^n[X_i>1]\)。

考虑什么样的 \(X\) 合法,发现 \(\sum X=2n-2\) 即可。

然后列式子 \(O(1)\) 计算即可。

提交记录

P2685 [TJOI2012] 桥 *

分别以 \(1\) 和 \(n\) 为起点建立两棵最短路树。找到一条从 \(1\to n\) 的最短路。

对于一条不在最短路上的边 \((u,v)\),找到在 \(1\) 为根的最短路树上 \(u\) 与 \(n\) 的LCA,记为 \(x\),找到在 \(n\) 为根的最短路树上 \(v\) 与 \(1\) 的LCA,记为 \(y\)。则当覆盖最短路径上 \(x\to y\) 的部分时,可以走 \(1\to x\to (u,v)\to y\to n\) 这条路径,设权值为 \(w\),于是在线段树上对 \(x\to y\) 这一段对 \(w\) 取 \(\min\)。

则答案为线段树中的最大值及其个数。

提交记录

P2481 [SDOI2010] 代码拍卖会*

很牛逼,还是说我太唐了。

首先第一步转化就很重要。因为每一位都不小于前一位,所以这个数可以拆成不超过 \(9\) 个的 \(1111111111\) (全为 \(1\) 的数)相加。

然后就是考虑一个位数不大于 \(n\) 的全为 \(1\) 的数对 \(p\) 的取模。对于每一个 \(i\) 求出有多少个不同位数的全为 \(1\) 的数满足对 \(p\) 取模后为 \(i\),记为 \(g_i\)。

这个怎么求?我们发现每一个 \(1111\) 的最后加上一个 \(1\) 就是对于 \(i\gets (i\times 10+1)\%p\),所以对于每一个 \(i\) 都有唯一的出边。我们建出图来后就是一个内向基环树。所以从 \(1\) 出发,走 \(n\) 步,则 \(g_u\) 为经过 \(u\) 的次数。那么直接分类讨论是在环上还是不在环上即可求出。

然后就是取不超过 \(9\) 个全 \(1\) 使得和取模 \(p\) 为 \(0\)。这个不难想到 dp。

中间需要求出有 \(m\) 个模 \(p\) 相同的全 \(1\) 数中选择 \(k\) 个可重且无序的方案数。这个就是:

\[\sum_{i=1}^k{m\choose i}{k-1\choose i-1} \]

然后 \(m\le 10^{18},k\le 9\),所以可以直接暴力求组合数。

对于每一个 \(i\),预处理出 \(g_i\) 个里选 \(0\sim 9\) 的方案数。然后直接 \(O(n^29^2)\) dp 即可。

提交记录

P2757 [国家集训队] 等差子序列

等价于判断是否存在三元等差数列。

发现在序列上不好做。于是转到值域上。

我们发现中间的数很特殊。考虑枚举中间的数 \(a_i\),那么剩下两个数依次在两侧,并且一个在前缀 \(a_{1\sim i-1}\) 出现过,一个没有。所以就相当于判断一个 \(01\) 串离 \(a_i\) 相同的位置是否全相等,如果相等则不存在,否则存在。那么可以直接用两个 \(01\) 串记录正序反序的哈希,用线段树维护即可。

提交记录

P5324 [BJOI2019] 删数*

我感觉这道题结论还挺好想的,但是为啥我想到类似的但是没有完全想到?

结论就是:我们记录 \(w_i\) 为数字 \(i\) 出现的次数,那么我们对于所有的 \(i\),若 \(w_i>0\),覆盖区间 \([i-w_i+1,i]\)。那么最小操作次数就是 \([1,n]\) 中没有被覆盖的位置。

这个其实很好理解,因为我们最后需要所有覆盖的线段刚好首尾相接,那么空的位置实际上和重叠的位置是相等的,我们只需要把重叠的部分中改一些到这个空的位置上去即可。

然后维护全局加时直接看作 \(0\) 在值域上的移动。只是有一个细节就是若 \(\exist i>n,w_i>0\),那么应该把线段 \([i-w_i+1,i]\) 删去。也就是我们只记录 \(i\in[1,n]\) 的 \(w_i\) 贡献的线段。

于是可以做到 \(O(n\log n)\)。

提交记录

P2566 [SCOI2009] 围豆豆*

这道题有一个 Trick 就是射线法,我们如何判断路径是否围住一个点呢?

我们考虑对于这个点向右做射线,记录状态初始为 \(0\),当路径每一次从上往下走到线上或者从线上往上走时就将这个点的状态异或 \(1\)。这样最终所有为 \(1\) 的格子都一定被包括在其中。

所以先枚举起点,然后直接记录 \(dp_{x,y,S}\) 表示当前在点 \((x,y)\),且状态为 \(S\) 的最小距离,直接跑 Dijkstra 即可。时间复杂度为 \(O(n^42^DD)\)。

提交记录

CF387D George and Interesting Graph

是不是不是很难。

直接枚举哪一个点是中心,然后把已经用了的边去掉。剩下的图需要满足是每个点都刚好在一个有向简单环内。所以把一个点拆成入点和出点,然后跑最大匹配即可。剩下的没匹配的边要删去,然后还要加上一些边即可。时间复杂度 \(O(n^2\sqrt m)\)。

提交记录

CF2217H Closer*

这个题说实话,我没想到一个好的 dp 状态,一直在考虑分类讨论,然后不可做。瞄了一眼题解的状态后就会了。

设 \(dp_{u,v}\) 表示最终换到 \(u\) 的点是 \(v\) 的最大权值。然后发现 \(u,v\) 一定相连才合法,于是状态数是 \(O(m)\) 的。

然后就是根据 \(u\) 这个点最终是什么然后计算其儿子和他的贡献。这真不难吧。

直接用 map 存状态,时间复杂度 \(O(m\log m)\)。

提交记录

P4769 [NOI2018] 冒泡排序

自主完成率 \(99\%\),中间有一步看了提示。

首先分析什么样的排列满足题目所给的性质,那么就有以下观察:

  • 若 \(i\ge p_i\),则 \(1\sim p_i-1\) 需要在 \([1,i-1]\) 中全部出现。
  • 若 \(i<p_i\),则 \(p_i\) 是 \([1,i]\) 中最大的。

所以就是可以刚好拆成两个递增子序列。

然后打了一下表发现长度为 \(n\) 的合法排列数刚好是卡特兰数的第 \(n\) 项。至于为什么当时没想明白。后来翻了一下题解,发现:

设 \(dp_{i,j}\) 表示 \(p_{1\sim i}\) 中最大值为 \(j\) 的方案数。

则有转移:

\[\begin{matrix}dp_{i,\max(i,j)}\gets dp_{i-1,j}& 填入第一种 \\dp_{i,k}\gets dp_{i-1,j}& 填入第二种,k>\max(i,j) \end{matrix}\]

初始 \(dp_{0,0}=1\),答案为 \(dp_{n,n}\)。

那么这个 \(dp_{n,n}\) 刚好就是从 \((0,0)\) 走到 \((n,n)\) 不经过 \(y=x-1\) 的方案数,也就是卡特兰数。

我们定义 \(f_{i,j}\) 为 \(dp_{i,j}\) 反过来的方案数,就是确定了 \([i+1,n]\),且前 \(i\) 个位置的前缀最大值为 \(j\) 的方案数,也就是从 \((i,j)\) 走到 \((n,n)\) 不经过 \(y=x-1\) 的方案数。这个可以 \(O(1)\) 计算。

现在考虑如何计算答案。

我们发现,记录每一个位置的前缀最大值后,前缀最大值构成的数组和原排列构成双射。原因很简单,只要前缀最大值发生变化,当且仅当这个前缀最大值大于 \(i\),则说明这里填的是第二种,否则就是第一种。并且这个第二种的数就等于前缀最大值。

于是考虑对于一个前缀而言,有多少排列满足这个前缀全部相同但是下一个位置大于给定排列。那么首先有一个条件就是这个前缀首先要合法,那么就按照上文给出的 \(i\ge p_i\) 和 \(i<p_i\) 判即可。然后设给定排列的这个位置为 \(i\),前缀最大值为 \(w_i\),那么这里的方案数就是 \(\sum_{k>w_i}f_{i,k}=f_{i-1,w_i+1}\)。

所以对于每一个前缀都计算即可。时间复杂度为 \(O(n)\)。

提交记录

AT_arc165_d Substring Comparison*

这个题乍一看毫无思路,但是可以直接考虑后缀之间的顺序。

首先如果两个区间的左端点一样,那么要么直接无解,要么可以无视。所以每一对区间的左端点都不一样。

现在考虑对于每一对区间维护两个指针 \(x\in[l_1,r_1],y\in[l_2,r_2]\),初始 \(x=l_1,y=l_2\)。然后对于所有 \(x,y\) 都先默认 \(x<y\),于是连边 \(x\gets y\)。

那么当这个图是一个 DAG 时就直接有解了。如果不是 DAG,那么一个强连通分量内的位置应该都相同。所以对于所有 \(x,y\) 如果 \(x,y\) 在同一强连通分量内,则直接将 \(x,y\) 都加一再连边。如果 \(y>r_2\) 则无解,如果 \(x>r_1\) 则直接不管这个限制。

然后直到所有限制都被无视了就有解。

时间瓶颈是跑 \(n\) 次强连通分量。所以时间复杂度为 \(O(n^2)\)。

提交记录

AT_codefestival_2016_final_f Road of the King*

这个题不难,但是我一直在想这个路径长啥样,有什么性质。

但其实直接去模拟 dp 就可以了。

设 \(dp_{i,j,k}\) 表示走了 \(i\) 步,走到了 \(j\) 个不同的点,其中有 \(k\) 个点可以走到 \(1\)。

转移非常简单。答案是 \(dp_{m,n,n}\)。

时间复杂度 \(O(n^3)\)。

提交记录

CF2147F Exchange Queries

是不是也不难。

考虑把第一个排列置换成 \(\{1,2,3,...,n\}\)。那么操作一二也可以换成只对排列二操作。

对于排列二,定义关键点为 \(p_{1\sim i}\) 的最大值为 \(i\) 的 \(i\)。设上一个关键点为 \(las\)(若没有则为 \(0\)),答案为 \((i-las)\times i\)。

考虑如何维护出所有的关键点。我们对于每一个 \(p_i>i\),将 \([i,p_i-1]\) 都加一,则所有值为 \(0\) 的位置是关键点。所以维护区间最小值和答案,就可以直接用线段树维护。

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

提交记录

AT_abc326_g Unlock Achievement*

这个题其实只有两种方向,一种是指数做法,还有一种就是网络流。指数级做法做不了,最多只能做 \(m\le 20\) 这种的。

这里网络流直接考虑切糕模型即可。

提交记录

也可以用最大权闭合子图做。

对于一个成就,建立一个点,点权为成就的收益,然后由这个点向 \((j,L_{i,j})\) 连边。然后 \((j,w)\) 向 \((j,w-1)\) 连边。点 \((i,w)\) 的点权为 \(-(w-1)C_i\)。这样就是一个最大权闭合子图问题。

AT_abc347_g Grid Coloring 2*

这个题的网格图没什么性质,所以考虑换成一般图,那么相邻的两个位置之间有一条连边,边权为 \((A_i-A_j)^2\)。

首先拆式子:

\[(A_i-A_j)^2=\sum_{t=1}^{A_i}(2t-1)+\sum_{t=1}^{A_j}(2t-1)-2\sum_{x=1}^{A_i}\sum_{y=1}^{A_j}1 \]

考虑建最小权闭合子图。

那么考虑对于 \(A_i\),拆成 \(5\) 个点,每一个点 \((i,w)\) 如果被选则说明 \(A_i\ge w\)。

那么 \(i\) 每有一条连边,就把 \((i,w)\) 的点权加上 \(2w-1\)。然后就是后面的那一坨就是对于所有的 \((i,x),(j,y)\),都额外建一个点 \(z\),点权为 \(-2\)。然后从 \((i,x),(j,y)\) 向 \(z\) 连边即可。

现在还要考虑有一些位置已经定了,设其值为 \(x\),那么 \((i,x)\) 就必须取,\((i,x+1)\) 不能取。如何刻画必须取和不能取呢?我们创建两个点,一个点权为正无穷,一个点权为负无穷,那么由负无穷连向所有必须取的点,然后将所有不能取的点连向正无穷的点。对于权值未定的点,那么 \((i,1)\) 是必须取的。

如何求最小权闭合子图?直接把点权全部取负,然后跑最大权闭合子图后将结果取负即可。

提交记录

P11948 [KTSC 2025] 完美编号 / numbering

简单题。

考虑一个简单环,那么这个简单环上的所有点都得赋值成一样的,否则一定会出问题。于是可以用边双缩点把整个图缩成一个树。

然后考虑树怎么做。我们希望把这些点赋值成若干个权值相同的连通块,使得这些连通块缩点后能是一条链。于是最终划分方式一定是一条从叶子到叶子的一条路径,这条路径上每一条边都被断开后,剩下的连通块各自赋值成一种颜色。

我们发现答案和所有连通块大小的平方之和线性相关,定义一种方案的权值为所有连通块大小的平方之和,所以只用考虑权值最小的方案。考虑 \(dp\)。

设 \(dp_{u}\) 为将 \(u\) 这棵子树内划分的路径的一端为 \(u\) 的最小权值。

因为路径会有一个深度最小的点,枚举这个点,于是有:

\[ans=\min _{u=1}^n \min_{v_1,v_2\in son_u,v_1\neq v_2}dp_{v_1}+dp_{v_2}+(n-sz_{v_1}-sz_{v_2})^2 \]

这个式子可以把后面的那坨东西拆开,于是可以用李超树 \(O(m\log n)\) 解决。

提交记录

CF407E k-d-sequence

简单吧。

首先找出 k-d 子段的充要条件:

  • 所有数 \(\bmod\ d\) 全相等。
  • 所有数都不相同。
  • \((\max-\min)/d+1-len\le k\),其中 \(\max,\min\) 为序列中的最大值和最小值。

那么首先把 \(d=0\) 给判掉。

然后对于每一个极长的 \(a_i\bmod \ d\) 相等的段进行计算,这样第一个条件就满足。让 \(c_i=a_i-(a_i\bmod \ d)\),于是条件三可以重新写成 \(\max-\min+1-len\le k\)。

考虑枚举左端点,扫描过去,同时维护对于每一个右端点的 \(\max-min+1-len\)。这个可以通过线段树维护,然后找到这个值 \(\le k\) 的最大的位置。更新答案即可。

时间复杂度为 \(O(n\log n)\)。

提交记录

posted @ 2026-10-26 20:11  Daylighten  阅读(2)  评论(0)    收藏  举报