「题集」精致的袖珍题目-2022 年度

「LG P1393」Mivik 的标题

题目链接:洛谷


L=|S|,设 s 为所谓名字的字符串。

前半部分算是非常套路。设 fk 表示随机生成一个长度为 k 的字符串后,它的一个后缀为 s,且 s 为第一次出现的概率。

不难发现答案就是 k=1nfk。这个状态的转移也是套路的容斥,也就是去容斥“第一次出现”。我们首先要保证没有 s 的结尾位置落在 [1,kL] 之间,那么此时任意组合的概率就是 (1j=1kLfj)×mL

接着对于结尾在 (kL,k)s 进行容斥,对于每一种不合法的情况,我们在第一次重复出现 s 的位置那里容斥掉它。前面已经保证了在 kL 之前不会有 s 结尾,因此之前的贡献可以用 f 计算。假设相交的长度为 l,则贡献应当为 fkL+l×mL+l,并且还需要满足 s[1:l]s 的一个 Border。

现在其实已经可以将问题写成多项式形式并使用半在线卷积计算答案了。不过,我们可以将 Border 划分为 O(logL) 个等差数列,这样每个等差数列中的 fkL+l×mL+l 可以直接前缀和维护,最终只需要维护 O(logL) 组前缀和即可优化转移。

小结:

  1. 注意这类问题的通用 DP 形式
  2. 注意使用等差性质优化转移的思想

「LOJ569」Misaka Network 与测试

题目链接:LOJ


就那么一个点要说的:我们总是优先选最小的满足要求的矩形。这个原则很容易推断出“单独选 2 格子”,但是很容易忘记这可以往后退一步——选完所有 2 之后,如果 13 相邻,那么就可以直接选走。按照这种方法选完之后就不可能剩下更多的满足要求的矩形了,因此可以直接跑二分图匹配。

小结:思考要足够深,想的时候稍微多想那么一步嘛。

「ARC103B」Robot Arms

题目链接:洛谷AT


首先思考无解的情况:不妨设我们对于 S 之中的操作,将 d 的权值赋成了 1。由于 x+y=i(1)[iS]di=idi2jSdj,所以所有 x+y 的奇偶性必须相同我们才可以构造出来。相应地,我们尝试在其它情况下构造出解。

这个问题,稍微摆弄一下就会觉得有一点比较奇怪:明明是上下左右四个方向移动,为什么一次操作对于某一维来说 +1,-1,0 有三种系数?这其实还是系数之间不是独立分配的原因。我们让系数独立开来,也就是每一维上要么是 +1,要么是 -1。这个可以直接通过将坐标轴旋转 45 并缩放达成

各维独立之后,整个问题就变得容易许多。类似于无解情况的构造方法,这个问题本质上就是凑数的问题,直接按照二进制配每一位即可。此外还有一点点化归想法:(x+y)mod2=1 的情况比 (x+y)mod2=0 的情况,我们于是加入一个长度为 1 的机械臂来调整即可。

小结:熟悉平面上常见的空间变换方式,同时多尝试一下独立变量。

「CF1267G」Game Relics

题目链接:洛谷CF


这道题比较需要观察能力。首先考虑任意一个购买方案,可以发现两点:

  • 每当我们开始随机,我们就一定会随机到新的物件才停止此轮随机,否则这(几)次随机都是无效的;

    根据这一点,我们可以用物件的全排描述一种购买情况,按物件来划分。

  • 当我们开始按原价购买时,我们之后都不会再进行随机。

    已有物件越多,随机到新的物件概率越小;相应地,花费越高,所以先随机一定不劣。

根据期望的线性性,我们可以将整个方案的期望花费,拆分为每买一个新物件的期望花费。因此考虑手头上有 k 件、未得到的价值和为 s 时的抉择。此时随机的期望花费为 x2(nk+1),而随机时期望占便宜为

1nkj(x2(nk+1)cj)=x2(nk+1)snk

因此可以看作期望花费 x2(nk+1)snk 选一个,直接选小的即可。剩下的就是一个简单的背包了。

小结:

  1. 使用交换等方式分析决策性质
  2. 利用期望的线性性拆开决策过程,便于日后计算;

「UOJ671」诡异操作

题目链接:UOJ


操作一直接势能线段树维护,注意特判 v=1,此外无甚可说;

操作二处理起来比较妙。一种方法是按位独立,各开线段树处理。但是这种处理方式不方便与操作一整合,因此我们也可以开一棵线段树,同时对于 128 位的每一位,记录当前位为 1 的个数和 and 标记。当然,这样做的复杂度为 O(logV(qlogn+nlogV)),下辈子也过不了。

下面就是奇妙的想象了:我们在一个长度为 L 的结点上,存了 128 个值,这些值的值域为 [0,L]但如果我们将这些值转化成二进制,我们不就在存储一个 128×logL 的 01 表嘛?为了更好地压榨计算机利用二进制运算特性,我们可以转换存储方式,用 logL__int128 存表而非 128 个 int 存。这样合并信息的复杂度降到了 O(logL)=O(logn)

分析复杂度:操作一至多造成 O(logV) 次每个结点的重构,因此复杂度为 O(logVlogL)=O(nlogV),而操作二可以直接视作 O(qlog2n),总复杂度即为 O(nlogV+qlog2n)

小结:

  1. 观察问题的角度很重要。首先当然需要找出问题的结症,而后是从多个角度去观察,开拓思路才可能解决。当然这里的处理也可以看作是“平衡复杂度”的操作;
  2. 高维数组寻址很慢,如果数组很大很常用,就用内存池

「POJ1927」Area in Triangle

题目链接:POJ


l 为绳长,cr 为内切圆周长,ct 为三角形周长。

lcrl=ct 的时候都很简单,略过。

关键在于怎么处理 cr<l<ct 的情况。可以想象在三角形里面塞了一个气球,往里头充气的时候气球会膨胀。不难发现在同等体积下气球倾向于保持表面积最小的形态,因此一顿 yy 之后就能想象出最终的形状为:

tri and cir.png

最后气球的形状就是 OM,MI,IK,KH,HL,LJ 这么围起来的一个封闭图形。相应的,我们要做的就是通过周长算出相应的面积。

注意到三个圆弧对应的曲率半径相同,因此我们很容易算出这个曲率半径。得到曲率半径之后,我们发现可以通过割补将三个扇形集中到一个圆形中,所以整个的面积就是 S+SS

小结:

  1. 解决几何的最优问题,通过合理的转化得到物理模型,再发挥想象,不失为一种好方法;
  2. 常用的平面几何技巧需要多积累,最怕的是知道但不会用......

「CEOI2010」Alliances

题目链接:LG


也是一道有一点小技巧的网络流题目,实在是太久没有做过网络流了......

问题主要出现在翻译题目上——如何将题目转化为等价的描述?这个题目中最难搞的“人类限制”,实际上就等价于:上下、左右各自最多只能同时贡献 1 的流量

当然也可以用 exclusion 的方式看待它:例如上下同时存在时,上下同时贡献了 2 的流量。而注意到上下、左右是互斥的,所以我们只需要保证上下不同时贡献 2 即可,左右类似。

「Gym102956D」Bank Security Unification

题目链接:CF


不套路的清新 DP 题。讲真这种类型的题目真真是我的弱项......

不难想到一个暴力的 DP,用 gk 表示 fk 作为序列中最后一个元素的最大序列权值。

说起位运算,我们常常可以联想到按位考虑。这题可以类似吗?看起来很劝退?

一般来说,DP 优化要么是合并状态,要么是踢状态。合并显然不现实,我们要“踢”,就得进行比较。在计算 gk 的时候,考虑 i<j<k,且fi,fj,fk 中都包含某一个 2t。则我们比较 i,j 的时候可以发现,同时选上 i,j 一定比只选 i。于是同时包含某一个 2t 的转移点,我们只需要考虑一个。对于所有的 t 动态维护一个最靠后的点即可。最终优化到了 O(nlogf)

小结:DP 的优化要么是合并相似状态,要么是剔除劣状态;此外还需要考虑切入点,比如在位运算的背景下,按位考虑就是一个始终值得下手的口子。

「CF1146F」Leaf Partition

题目链接:LG


可以发现,所谓 f(L) 其实就是 L 点集生成的虚树。

我们可以从底向上考虑问题:先将每棵叶子单独划分进某个集合,而后在每个结点上考虑合并某些集合——这个过程显然易于列 DP。这个过程中,我们不妨认为我们在动态维护虚树,所以可以列两个状态:fu 表示将 u 子树内的叶子划分入若干个集合的合法方案数,而 gu 表示,所有不同的虚树形态的个数

g 状态是为了解决这样的问题:如果 u 没有被覆盖,且 u 的子树内有多棵可以向上延伸的虚树;则在 fu 内这种情况只会被计算一次,但如果在 u 的祖先处 u 被覆盖,那么它的子树内的虚树是不能看作同一棵的,因此需要多计算几次。

g 实际包含了两种情况:

  • u 成为了某棵虚树的根;
  • u 不是某棵虚树的根,此时我们需要从它子树内可以向上延伸的虚树中,选择一棵并将它的根一路上提到 u(并将路上的结点也算在那棵虚树中)。如果选择的虚树不同,则即便划分方式相同也会被算多次。这也就是所谓“虚树形态的含义”;

小结:自底向上动态维护虚树的 DP 还是挺有意思的。

「CF285E」Positions in Permutations

题目链接:LG


首先,这道题的难点之一是不要读错题目

注意题目中 beauty 定义为两两差最小值,所以这个东西与顺序无关,序列可以被排序。之后,我们尝试枚举 beauty 值计算相应的序列个数。计算序列个数可以做到 O(nk),不多说。关键在于,我们发现beauty 值的值域其实并不大。排序后可以分析出,beauty 的一个上界为 maxak1,因此复杂度为 O(nmaxa)

平时对数值就不是很敏感,对于这种值域明显比较小的问题一定要注意值域信息。如果确实分析不来,直接用其它方法剪枝,可能也会得到正确的复杂度。

「JSOI2019」精准预测

题目链接:LG


显然可以构建按照 2-SAT 的方式构图。(需要注意,题目别读错了!!!)

压缩后,图的大小是 O(m+n) 的。对于某个人 k,他实际上只有两个需要注意的点:akdk。我们需要解决:

  • ak 能否到达 dk
  • ak 能到达多少个 djjk

可达性问题显然可以使用 bitset 来处理,问题是直接做空间复杂度为 O(n(n+m)ω)

注意到,dj 之间是相互独立的。为了平衡,我们可以分成若干次询问,每次处理的关于所有 dj,j[l,l+S) 的问题。

这也是类似于复杂度平衡的思想,只不过是平衡时间与空间。这也是一种离线的处理方法,事实上 Methods of Four Russians 中,也有不少可以类似的离线处理、压缩空间。

「Gym 101630J」Journey from Petersburg to Moscow

题目链接:Gym


显然可以直接枚举一个阈值 t,而后假装所有 t 的边在路径上都得收费,而 <t 的就不用收费了。暴力做需要记录经过了多少条需要收费的边,复杂度为 O(mn2logn)

可以想到用 WQS 二分来将一个 n 换成 logV。二分一个 δ,对于 t 的边,全部减去一个 δ。为了避免出现负数,我们控制 δt。可以发现这样并不会出错,因为如果 δ=t 之后都还没有出现合理的路径,那就说明这个 t 实在是太劣了。

但当我们想到了“减法”这种技巧的时候,我们只需要再深入一步——对每条边都减去阈值 t,并对 0 取 max。这样跑 Dijkstra 之后,再加上 kt,就一定不会多算答案。

我们其实只需要保证某些 t 的边数量不足 k 的路径不会被错误地计入答案即可。首先,这些路径会在对应的 t 的枚举情况中计算到。而此时这些路径上作为前 k 大的某些边,它们的权值会变大,因此计算长度长于实际长度,没有影响。

小结:求最值简化问题无非两个角度:弱化限制或者缩小搜索空间——这道题用的就是前者。但想到这个“减法”的方向可能还是需要动一下脑筋,最好留个印象!

「SDOI2017」天才黑客

题目链接:LG


这道题虽然被放在了这里,但是它实际上真的一点一点一点也不“袖珍”。

把题目读懂之后就会明白这道题的方向是优化建图

第一个步骤,如果真真暴力的话会建出来 O(nk) 个点,肯定没法做。但是仔细一想就会发现,某种口令在结点 u 处有效,当且仅当这个口令在任意一条邻接边中出现过。因此有效的状态个数马上被压缩到 O(m) 种。

第二个步骤,如果暴力一点,在某个结点处,对于所有口令状态交叉连边,那么可能会连出 O(m2) 条边然后爆炸。不过,由于这道题有 Trie 的背景,因此可以想到在 Trie 上进行优化的动作——Trie 上两个字符串的 LCP 为 LCA 的深度。如果对于每个结点都复制一棵 Trie 当然也会爆炸,不过既然边权只和结点深度有关,因此可以想到用虚树压缩

由于某些原因,我们必须保证连出来之后路径上边权恰好经过 LCA。那么考虑两种情况:

  • LCA 为端点,这个时候可以直接树上前后缀;
  • LCA 不为端点,此时可以枚举 LCA,并保证必须在跨子树的时候才能进行贡献——显然可以直接对于儿子进行前后缀优化

小结:

  1. 点太多的时候要主动去压缩状态
  2. 这里关于 LCA 的建图还是挺有意思的;

「联合省选 2020 A」树

题目链接:LGLOJ


还是挺有意思的,用到的算是一个 Trie 的小技巧。

我们需要维护全局 +1 之后的全局异或和。研究一下,发现 +1 就是将最后一段 1 全部翻成 0,然后再将后面跟的 0 变成 1。不过,一个递归的视角可以展现更多的东西:

如果 x 是奇数,则 x+1 为偶数,且恰好为 x2 +1 后的结果再 ×2;否则,结果就是 x+1

Trie 上,偶数 +1 直接调换儿子即可;而奇数 +1 可以如上递归调换右儿子。所以,最终复杂度可以做到 O(nlogn)

「SDOI2013」保护出题人

题目链接:LG


看到“除法”,就应该想到两点间斜率这个备选项。

想到最大化斜率,就不难想到上凸包优化了。

「SDOI2014」LIS

题目链接:LGLOJ


这题还是有一个要点的:关于最小割的可行边和必须边的问题

可行边:对于一条边 e,如果存在一个割边包含 e 的最小割,则它就是一个必须边。

对于边 uv,它作为可行边存在的条件是:首先,它必须满流;此外,割掉它之后必须得起效果,因此残量网络上从 u 不能到达 v。这道题实际上就是要求我们按照 C 的顺序逐个取出可行边,并在残量网络上固定修改。前者我们已经知道如何解决了,而后者则是还原之后重新跑一边最大流就可以完成的任务。

必须边:对于一条边 e,如果对于所有的最小割,e 都作为割边存在,则它是一条必须边。

对于 uv,它作为必须边存在的条件是:首先满流;其次,我们得保证如果不割掉它,s 就必然可以到 t,反映到图上,这就意味着残量网络上从 s 可以到达 u,而从 v 可以到达 t

此外还有随便构造割的问题——设 Vs 为残量网络上 s 可以到达的点的集合,我们直接构造为 [Vs,VVs] 即可。

小结:网络流上关于割的构造问题还是相当值得注意一下的

「CmdOI2019」星际kfc篮球赛

题目链接:LG


这题总给人一种缝合怪的感觉。不仅缝合,还很怪

前半部分需要建出完全图上的最小 xor 生成树......的 Kruskal 重构树。求最小 xor 生成树是经典问题,直接在 01 Trie 上面贪心即可,此外事实上可以直接在求最小生成树的过程中将重构树建出来。

特别注意:当 01 Trie 有两个儿子的时候,我们在两个儿子的连通块之间,只会连一条边

后半部分比较神奇。如果直接做比较麻烦,因为我们相当于考虑 3 个区间、6 个偏序。但是,注意到这里的区间限制是可以差分的,因此可以将前面两棵树的区间限制转化成前缀限制,而后跑莫队,用分块或 BIT 维护第三棵树即可。

特别注意:莫队复杂度为 O(nq),理论上最优块长应该是 O(n2q)

「ARC076C」Connected?

题目链接:AT


容易发现,只有两个端点都在边界上数的才会决定答案。事实上我们只需要检查这些数直接连成线段之后交不交就可以了。

注意到,矩阵的边界对应的其实是一维的情况。我们考虑把边界直接展开,这样的话原先的线段拍到直线上,就是一个匹配关系。我们只需要保证这样的匹配关系不交(或者,形成类似“括号匹配”的结构)即可,排序之后检查就可以了。

话说我直接写一个暴力判线段交不交的程序为啥 WA 了?

「ARC076D」Exhausted?

题目链接:AT


特殊图的二分图匹配,Hall 定理是一个很好的切入角度。

最开始想的是,存在完全匹配的某个左部集是否满足拟阵性质?证不来,但是写了一下,发现会 WA 几个点。

事实上,由 Hall 定理可以得到一个很重要的推论:设 n(S) 为点集 S 的邻接点集,则二分图的最大匹配为:

|VL|maxSVL{|S||n(S)|}

如果将这个定理运用到本题上,我们可以将 n(S) 取补集,这样原先的并集就会变成补集的交集。计算一下,最终只需要最大化:

maxSVL{|S||VRn(S)|}

这个容易放到区间上,再使用线段树维护。

小结:主要是想记录一下这种 Hall 定理的用法,在特殊二分图最大匹配中应该会比较有效。此外,还应该了解一下 Hall 的 t-条件,这是一个充分的条件(原 Hall 定理是充要的)。

「CF672E」Orchestra

题目链接:LGCF


主要的难点在于:首先要想到“卡上下界”然后枚举的 O(r2c) 的思路,其次还得注意到,这个东西会因为 k 很小而可以优化

想到了这个方向之后,再去考虑如何动态维护,以及倒序删除之类的,都不是很困难。

小结:最开始一定不能把思路限制死了,多留几个出路,方便之后能有选择。如果要找,则最好从暴力入手,并且要提供一定的时间给可能的方向,而不能直接叉掉。

「ARC016D」軍艦ゲーム

题目链接:LG


显然可以写出一个 DP:设 fu,h 表示从 u 出发,当前血量为 h 时的期望步数。

转移比较神奇:

fu,h=min{f1,H+Hh,1du((u,v)Efv,hdv)+1}

不妨认为 fn,x=0,x>0fu,x=+,1u<n,x<0

这个转移奇妙的地方就在于,它几乎没有出现了环——除了所有状态都有可能联系到 f1,H 以外。为了消除后效性,我们尝试将 f1,H 作为变量,比如叫 x并枚举它,然后再检查。

更进一步地,尝试加速这个过程。一个想法是,二分 f1,HA,并以 f1,H=A 来计算,检查最终结果是否 A。这个做法是对的,因为我们注意到最终 f1,H 可以被表示为若干条关于 x 的直线取 min——众所周知,会构成一个凸包。而这个凸包斜率总 1,因此和 y=x 只会有一个交点,我们相当于在尝试二分这个交点。

小结:

个人感觉,f1,H 看作变量观察 f1,H 为凸包结构并进行二分,这两点比较好。

「PA2014」Druzyny

题目链接:LG


启发式分治优化 DP。被卡住的地方是——cd 的关系并不是等价的

如果我们把 c 拿来分治,则 d 的后缀最小值和区间长度是异调的,这样只考虑 d 时,每个右端点/左端点的可用左端点/右端点是单调的。但是,如果先入为主地将 d 拿来分治,则 c 没有这样好的性质。

虽然两者在分治过程看是等价的,但是在分治之外就不是。

「CF822E」Liar

题目链接:LG


我是 sb,我光知道按着 t 来 DP,不知道可以按着 s 来 DP。如果把 s 的匹配状态压到 DP 状态里,则 t 必须连续匹配,而 s 的不连续可以用前缀转移来优化掉。这样再配合后缀数组就很简洁了。

小结:

总得来说也是和上一节一样的,要明智地回退

但是终究很难落实,什么时候该回退,什么时候不该,说不清楚。

与其乱撞,倒不如一开始就利用好其中匹配的性质,同时利用好 DP 转移的简便性

「LGP5824」十二重计数法

题目链接:LG


最后一个整数拆分,限制盒子数,从那个原始的 O(n2) 入手就可以了

误以为这个东西没法优化,居然试都不试一下。这种错误应该尽量减少!
小结:

避免先入为主的想法,如果遇到困难时一定要留下“回溯”的选项!!!

「LOJ6243」关灯问题

题目链接:LOJ


这道题像是脑筋急转弯啊。纯高消的话时间不会低于 O(n4ω),还需要 band matrix 的 trick。

显然,我们只能考虑列几个主元出来。但是,如果我们单纯地提一行一列出来,或者提一行出来列主元,则没有办法消掉环。

怎么办呢?观察一个方程的形式:

xi,jxi1,jxi+1,jxi,j1xi,j+1=a

稍微移一下项,发现如果推出一个新的变量,需要至少两列/两行的变量。所以把前两列/前两行都列入主元就好了!

小结:列主元本质是希望通过方程生成递推关系,所以应当从方程入手,确定哪些应该变成主元。

「UVA11754」Code Feat

题目链接:LG


k 比较小的时候,直接枚举所有解就可以了。

而当 k 比较大的时候,根据题解的说法,可以枚举一组限制并生成所有可能的解,再拿去判断是否满足其他解。此时,可以选取 kX 最小的来枚举,但是复杂度仍然未知。

小结:本来想记录一下枚举部分限制的解,再将这部分解拿来检验的这种思路;不过看来也遗留下来了复杂度的问题 😅。

POI 两道字符串

题目链接:「POI2012」PRE-Prefixuffix


显然我们需要枚举一个 Border。问题在于,如何尽快求出去掉一个 Border 之后,剩下的串的 Border?

不妨设 fk 为,删掉前 k 个字符后,剩余字符串的 Border 的最大值。从 fk+1fk,加入字符似乎不好处理,那么反过来,考虑删除字符,此时就容易发现有 fk+1fk2,也即是 fkfk+1+2。这样就给 fk 定了一个上界,我们再按照删除的顺序做即可。


题目链接:「POI2005」SZA-Template


写了一个 Border 链 + 线段树的 zz 做法,不想说了。

fk 表示前缀 [:k] 的答案,则会发现性质:fk 要么是 k,要么是 fnxtk。这其实就是在 Border 中隐含的递推关系,而直接维护 Border 链就是将这一层递推关系展开后的愚蠢做法。

检查是否可以取到 fnxtk 是容易的,这里不再赘述。

小结:在扫描过程中,对于 Border 的处理其实很像是在做 DP,我们要么转移到一个新状态,要么转移到一个可以由 Border 计算好的状态。在其他后缀结构中也有这个性质,所以不要每次都想着显式地展开后缀链处理!

「CF453D」Little Pony and Elements of Harmony

题目链接:LG


取模才是最复杂的部分 😅。

在 IFWT 的时候,我们可以把所有的 12 全部提出来,也就是最终只需要整体除掉一个 2m。由于 modp 意义下不可能这样随便除,我们可以考虑扩到 p 的一个倍数的模下面运算,保证在那个范围之中可以除掉这个 2m,再还原到 p 的模即可。

有了这个思路,就不难想到扩到 2m×p 了。

「WC2018」州区划分

题目链接:LG


这道题,最后虽然看似需要“分治卷积”,但你思考一下,既然子集卷积已经需要记录集合大小了,那么直接按照集合大小来从小到大卷积,就已经足以保证转移的单向性了!

「Gym102956A」Belarusian State University

题目链接:Gym


这道题告诉我们:

  1. 所谓集合卷积,实际上就是多元卷积,这样就隐含了独立性。

  2. 尝试通过已有的结果,进行一定的变换之后解决问题,这样的思路总是值得考虑的。

    尤其是像这一道题目,既然只有 16 种真值表,那么尝试直接转化到 3 种基础的卷积也是合情合理的。

「LG P5349」幂

题目链接:LG


直接转下降幂多项式是愚蠢的,根本不需要思考的好伐?

尝试使用一些基本的数学方法来解决这个问题。本质上只需要求出:

Sk=n0nkrn

套用错位相减法,可以得到最终的结果为:

Sk=11r([k=0]+j=0k1(1)kj+1(kj)(Sj[j=0]))

然后分治 FFT。

小结:回归基础方法。一些技巧固然可贵,但是根本的路径是不能被随便遗弃的......

posted @   crashed  阅读(535)  评论(4编辑  收藏  举报
相关博文:
阅读排行:
· 阿里最新开源QwQ-32B,效果媲美deepseek-r1满血版,部署成本又又又降低了!
· 单线程的Redis速度为什么快?
· SQL Server 2025 AI相关能力初探
· AI编程工具终极对决:字节Trae VS Cursor,谁才是开发者新宠?
· 展开说说关于C#中ORM框架的用法!
点击右上角即可分享
微信分享提示