本文废了,转到 https://po7ed.github.io/problem-summary/。
本文存放了好题的简要题意和题解,方便复习回顾。
?
题意
思路
点击查看题解
代码
https://www.luogu.com.cn/record/
P4025
题意
初始时 , 个操作依次进行,每次将 ,,求安排操作的顺序使得全程 。或判定无解。
思路
点击查看题解
代码
https://www.luogu.com.cn/record/136130626
P6146
题意
条线段,定义若干线段的复杂度为它们的并形成的连通块的个数。求 条线段所组成的集合的所有子集的复杂度 。
,。
思路
点击查看题解
以左端点排序,设 的答案为 ,则第 条线段有两种可能:
- 不取,复杂度之和仍为 ;
- 取,考虑哪些子集复杂度有变化()。显然,这些子集必须满足其中没有任何一个元素(线段)与第 条线段相交。即这些子集必定是 所有不与第 条线段相交的线段(的集合)的子集。我们可以用前缀和求出右端点 的线段数量 ,那么那些子集的数量即为 。每个子集贡献为 ,复杂度之和为 。
于是 ,递推计算即可。
代码
https://www.luogu.com.cn/record/141604463
P6503
题意
给出一个长度为 的序列 ,求出下列式子的值:
。
思路
点击查看题解
考察:单调栈,技巧。
首先化简,变为
分别求值。
技巧:反向枚举:原本是枚举区间求最小值,现在枚举最小值求区间。
钦定区间最小值为 ,求有那些区间满足条件。显然对于一个极大的区间 ,若其中最小值为 ,则 且 。于是只需要求左边、右边最近的大于 的数的位置即可。
求出 后,答案则为
其实还没完,对于相等的情况,可能有某个区间内有多个最小 / 大值。这样可能使答案偏大,为不重复计算,假定只有最左边那个极值能产生贡献。于是左端点 应是左边最近一个小 / 大于等于 的右边一个(左边不取等),右端点 应是右边最近一个小 / 大于 的左边一个(右边可以取等)。微调一下单调栈内不等号即可。
代码
https://www.cnblogs.com/chargedcreeper/p/17962041
https://www.luogu.com.cn/record/127429185
P6649
题意
的网格从第 行走到第 行结束,可以往左、上、右走,但对于每一行,不能走到 第一次来到该行的位置 的右边。求得分最小值。
。
思路
点击查看题解
考察:dp,最小子段和。
可以发现对于每一行必然有:在这一行走到的最左边 ,走到下一行的位置 ,从上一行来到这一行的位置 ,同时 。
考虑设 表示现在在 的最优解,发现无法转移:因为不知道第一次来该行的位置,可能走出不合法的路径。于是设 表示现在在 准备走到下一行,此时的最优解。求出最小子段和 ,同时计算向后的最小子段和 。相加即为答案。
代码
https://www.luogu.com.cn/record/135797772
P7074
题意
行 列方格图从左上角走到右下角,不能重复走一个方格,每次可向右、上、下走,最大值路径上数的和。
思路
点击查看题解
考察:dp。
只能考虑 dp。若设 表示从 走到 的最大和,可以发现无法保证不重复,无法转移。
考虑再细分状态。发现如果从 走到 ,则不能往回走。也就是说,状态可以保存来时的方向,这样就能保证不重复。具体看代码。
代码
https://www.luogu.com.cn/record/165721514
P7167
题意
个圆盘从上到下排列,第 个圆盘直径为 ,容量为 。倒水时若当前圆盘满了,则流到下面第一个直径大于当前圆盘的圆盘。最下面是编号为 的水池,充分大。
给定 组互相独立的询问,第 次询问形如向第 个圆盘里倒入 的水,求水最后会流到哪一个圆盘停止。
。
思路
点击查看题解
考察:树,倍增,单调栈。
可以发现流水的关系是一棵树,可以使用单调栈求出。问题即转化成跳多少次父亲,使得路径上水被消耗完。
暴力跳不行,考虑倍增。用倍增数组求出点 向上跳 步跳到哪个点、途中消耗水量。询问时直接从大到小尝试 跳即可。细节小多。
代码
https://www.luogu.com.cn/record/129490916
P7913
题意
个廊桥分给国内、国际两部分。有 架国内飞机, 架国际飞机,每架飞机有到达、离开时刻 。
廊桥先到先得,求分配的最优方案使得最多飞机停在廊桥。
, 且互不相同。
思路
点击查看题解
考察:前缀和,思维。
先忽略廊桥数量的限制。维护一个空闲的廊桥队列,每到达一架航班,就给它安排编号最小的廊桥供其使用,求出每个廊桥停靠的飞机数 。
加上廊桥数量的限制,可以发现直接就解决了问题。枚举国内分配几个,求出国际有几个。对廊桥停靠的飞机数前缀和 ,代表停靠廊桥编号小于等于 的飞机个数,也即分配 个廊桥时停在廊桥的飞机数。国内、国际相加取最大值即为答案。
代码
https://www.luogu.com.cn/record/128834774
P7915
题意
给定一个长度为 的双端队列 ,其中 各出现 次。有一个空的 序列,每次将一元素从 出队(从开头或结尾均可)放入 末尾,要求 为回文序列,求字典序最小的操作方案。无解输出 。
。
思路
点击查看题解
考察:注意力,贪心。
可以发现如果第一次取出 开头元素,则另一次出现该元素的位置一定是最后一个出队的,因为该元素需分别处于 的开头、结尾来实现回文。取出 结尾元素同理。
该元素另一个出现位置将 划分为两个栈,栈底分别为上述位置的两侧。
具体来说,若有 ,则两个栈(栈底到栈顶)分别为:
- ;
- 。
若 同理:
- ;
- 。
问题转化为:每次从两个栈顶中选一个出栈,放入 末尾,使 回文。
类似的,注意到如果取出了某个元素 ,则另一个 必须最后一个出栈。即 必须同时存在于栈顶和栈底(具体在哪个栈、是否在同一个栈并不重要)。这样,如果删去 对最优解没有影响。
于是,可以将栈改为双端队列,只需寻找这样的 ,将它们两个同时出队,保存答案即可。如果找不到 则无解。如果有多个 取使字典序最小的。
第一个元素有两种取法,需分别求解。
代码
https://www.luogu.com.cn/record/158843287
P8059
题意
给定一棵 个点的树,每时刻都有边断裂(共 次),断裂后与根( 号节点)不连通的部分称为在该时刻掉落。求每个点的掉落时间。
。
思路
点击查看题解
考察:正难则反,dfs。
连通性相关删边题目考虑正难则反,求出每个猴子第一次与 连通的时间。每次断裂(连接)时在子树中 dfs 打标记。
代码
https://www.luogu.com.cn/record/129895749
P8287
题意
个源点,每单位时间流沿边流动,求形成环的最短时间。
。
思路
点击查看题解
考察:二分,并查集,b/dfs。
两种做法。
第一种是注意到答案有单调性,直接二分答案。预处理边满流的时间,对于当前子图判断是否有环(通过搜索)。可以使用并查集,但没必要。直接 dfs 判断是否有横插边/返祖边即可。
第二种运用 bfs + 并查集。bfs 过程中,
- 若子状态未访问过,当前状态与子状态合并。(状态就是点。)
- 反之若访问过,则检查是否为同一集合,
- 同一集合则更新答案为 ,
- 反之合并二状态。
同时需维护 表示 至源点最近距离(耗时)。
代码
https://www.luogu.com.cn/article/fuc7vj7c
https://www.luogu.com.cn/article/3slxhfa4
https://www.luogu.com.cn/record/130565732
P8675
题意
有一个 的图纸,从下往上搭积木。每块积木必须紧挨着放置在某一块积木的正上方,最底层除外。同一层中的积木必须连续摆放,标有 X
的位置不能放置积木。求方案数。
。
思路
点击查看题解
考察:区间 dp,前缀和优化。
对于每个方案,可以由 表示。 分别表示第 层的左右端点。
自然的 dp:设 表示已摆了下面 层,第 层摆放为 的方案数。转移方程:
边界
答案即枚举搭 层,累加即可。
注意 从 开始,即包括啥都不搭的方案。
代码实现略有不同。
代码
https://www.luogu.com.cn/record/126394295
P8815
题意
求仅含 &
和 |
的逻辑表达式 的值和二运算符的短路次数(分别)。
。
思路
点击查看题解
考察:模拟。
表达式求值,考虑栈模拟(其实没有栈)。
- 如果前面已经短路,
- 有左括号跳括号,跳完为止;
- 若为右括号,则短路结束;
- 如果为
0&
型短路且当前为|
,即0&...|...
,则有0|...
,短路结束; - 反之为
1|
型短路且当前为&
,即1|...&...
,则无关紧要; - 若
0&
型短路且当前为&
,即0&...&...
,直接丝滑小连招继续短路; - 若
1|
型同理。
- 反之前面没有短路,则前面都没有影响,另起炉灶,
- 若遇到数,则将值暂时置为该数;
- 若有短路,则设置为相应短路状态。
代码
https://www.luogu.com.cn/record/125789473
P9209
题意
将 辆车按顺序停在 个停车位中,对于第 辆车,如果当时停放时左边有连续 个空位,右边有连续 个空位,那么它将需要 单位时间停放。求最小总耗时。
。
思路
点击查看题解
考察:贪心。
最小化 即最大化 。当 时发现应让 尽量大,即放在最右边,反之亦然。故每次只可能停最左和最右边。故停第 辆时,有 ,直接计算即可。
答案为
代码
https://www.luogu.com.cn/record/126720348
P9474
题意
在元素互不相同的长度为 的数列 中选出一个长度为 的元素互不相邻的子序列,使得子序列的极差最小。
。
思路
点击查看题解
考察:双指针,思维。
显然存在 的暴力 dp 做法。
发现有 的数据,保证 单调递增,同时因为“不相邻”是一个相对弱的条件,考虑将 排序(需保留原下标)。可以枚举左端点,求最靠左的右端点,使得区间中可以组成合法子序列。
容易发现右端点是单调的,即若 的右端点为 ,则 的右端点 。
接下来考虑怎样快速求一段区间能组成的最长合法子序列长度。如果从值下手,此题类似于最大的独立集问题(即有若干互不相同的元素,有若干条件诸如某两个元素不可在同一集合内,求最大的集合大小。可以抽象成图。),很难下手。不妨换个角度:直接将当前区间内所有元素按原下标填入一个新序列中。新序列可能有位置空出,也有若干连通块。设各连通块长度为 ,则最长合法子序列长度为
例如:对于 ,排序后 。
对于 上区间 (即 ),以原下标填入 ,肉眼可见有两个连通块。第一个连通块可以选出 个数,第二个可以选出 个数,相加即为 。
再比如区间 (),填入 ,最大长度为 。
“填入序列”可以使用类似珂朵莉树(ODT)的方法,维护若干现有区间。移动左端点时即删除左端点,看情况缩小区间或分裂。移动右端点即添加新右端点,看情况扩大区间或合并即可。
代码
https://www.luogu.com.cn/record/117195632
P9751
题意
点 边有向图,第 边在时刻 出现,通过均耗时 单位时间。
在 的非负整数倍时刻从 号点出发、 号点离开。不能在任何地方停留。
求最早离开时刻。无解输出 。
。
思路
点击查看题解
考察:二分,最短路,分层图。
此题显然不是简单的最短路。去除“边出现时刻”的限制,我们假定现在所有边都存在。
可以发现,由于边权均为 ,最短路退化为 bfs。
同时由“ 的非负整数倍”这一表述(以及 的小范围),注意到对于两个状态(路径),如果他们的长度(耗时)在模 意义下同余,则它们重复了。即只需保留耗时更短的状态。因为对于耗时更长的状态,其接下来可能的行动都可以“移植”到耗时更短的状态上,从而被替代。
但是对于两个耗时在模 意义下不同余的状态,若其中一个状态有解或无解,与另一状态无关。因为它们的余数不同,可行的路径或是否无解也不一定相同。
于是在 bfs 判重的 vis 数组中,需要新增一维属于模 同余值。如果队头状态处于终点 ,且耗时为 非负整数倍(即模 余 ),则到达目标状态。
这相当于将每个点拆成 个,分别表示余数。
接下来考虑“边出现时刻”的限制。
一个做法是二分开始时间,按条件 bfs,对每次的耗时取 。这样做正确性比较难证。
另一种做法是二分结束时间倒推。
更好的做法:发现能在起点等 的非负整数倍相当于能在任意点等 的非负整数倍。转移时若时间未到,直接在原地等 的负整数倍时间直至可以通过。易证这样一定是最优的。注意到这样边权不全是 ,跑 Dijkstra 即可。
代码
https://www.luogu.com.cn/record/134470526
P10134
题意
头牛,每头牛有分数 满足 。有 条限制条件,每条形如 为第一个严格大于前 头牛分数的牛()。有一些分数被 FJ 忘了,求字典序最小的分数序列。多测。
。
思路
点击查看题解
考察:
https://usaco.org/current/data/sol_prob1_silver_jan24.html
我们定义 为第一只严格大于前 只牛分数的牛的下标。这很有用,因为 FJ 的记忆限制可以表述为 。为了简化公式,我们同时设 ,即前缀最大值。
对于 ,我们显然有
- ;
- 。
对于 ,显然有 ,反之可以证明矛盾。故如果存在两个限制 ,满足 ,无解。综上所述,对于任意 ,我们可以得出 的值(为 )。对于其他 ,我们称它们未知。
这足以使我们得出一个贪心的算法:枚举 从 到 ,存储满足 约束条件 的最小值。
对于一个确定的 ,如果 未知,则无需操作。反之则有两种情况;
- :可以发现这并没有对 施加额外的约束,因此我们不必修改它。 有一个相关的变化,我们将在下一个情况后讨论。
- 反之 ,我们需要找到一个 并将 设为 。但是,
- 首先 需要尽可能大,且 不能被题目给定。因为我们希望答案的字典序尽可能小。
- 其次不应存在 使得 。否则修改后 ,矛盾。
- 因此如果不存在满足上述二条件的 ,无解。
对于两种情况,我们都需要保证 。若 没有给出,则可设为 。反之若 已经给出,我们需要保证它至少为此值(即满足 )。若无法满足,无解。
这种算法之所以有效,是因为每增加一个约束条件,就只能产生一个等价或更大的词典序列。因此,通过在数组中尽可能靠后的位置进行修改,得到的序列就是词典最小序列。最后,只需遍历序列,确保所有值小于等于 ,以检查问题中的最后一个约束条件是否满足。
时间复杂度 :https://www.luogu.com.cn/record/164344021。考虑优化。
第一部分即填写 可以使用双指针优化。具体的,枚举 ,维护 ,如果需要,则令 从 移动 填写。如果发现 需要倒退并填写不同的值,则无解。
第二部分即构造 。可以发现如果满足了 的条件,那么 都可以跳过。于是我们有了时间复杂度 的算法:https://www.luogu.com.cn/record/165903355。
代码
https://www.luogu.com.cn/record/164344021
https://www.luogu.com.cn/record/165903355
P10190
题意
个矩形目标依次出现、消失(每个时刻最多只存在一个目标)。每个目标的左侧边在同一条直线 上。 头牛向矩形目标顶点射箭,要求箭不可穿过目标内部。每头牛有固定的射击角度,用斜率表示,即牛射击时箭的轨迹(直线)的斜率必须为给定的值。牛均站在 轴上。求最远奶牛之间的最小距离是多少,或报告无解。多测。
。
思路
点击查看题解
https://usaco.org/current/data/sol_prob1_silver_feb24.html
考察:二分,贪心。
首先可以发现右上角的顶点只能使用负斜率牛射,右下角的顶点只能用正斜率牛,反之会穿过目标内部。也就是说,我们至少分别需要 值正、负斜率牛,否则无解。
剩下的 头牛分给左侧顶点。可以对左侧所有点按纵坐标排序,纵坐标大的分配负斜率牛,纵坐标小的分配正斜率牛。可以证明这样一定最优。
发现正斜率牛决定下界,负斜率牛决定上界。将两种牛(上界、下界)分开考虑。以下界为例,二分下界,求出每个点与下界连线的斜率,即射这个点的牛斜率必须不大于该值,反之会超出下界。将所有限制排序,与牛排序后斜率一一对应,若无法满足则当前下界不可取。反之可取。
代码
https://www.luogu.com.cn/record/166205046
P10277
题意
名农夫面试 头牛。
时刻 ,,农夫 面试奶牛 。第 头牛面试花费 分钟。一旦一名农夫完成面试,他将立刻开始面试队列中的下一头奶牛。如果多名农夫同时完成,下一头奶牛可以根据自己的偏好选择接受任一此时空闲的农夫的面试,每头牛偏好未知。
求第 头牛面试开始时刻和可能面试她的农夫。
。
思路
点击查看题解
考察:思维。
由于每头牛面试的时间与选择那个农夫无关,故可以先求出每头牛面试的开始时间 和结束时间 。解出第一问。
考虑哪些农夫可能面试第 头牛。
我们称一个时刻是重要的,当且仅当任意农夫在该时刻结束面试,便有机会面试第 头牛。
显然 是重要的。其次,我们可以推出若时刻 是重要的,且 ,那么 也是重要的。因为我们可以通过面试第 头牛,实现在 时结束对牛 的面试。于是我们可以推出所有的重要时刻(或在重要时刻结束面试的牛)。
对于任意 ,如果第 头牛在重要时刻结束面试,则第 名农夫有可能面试第 头牛。
代码
https://www.luogu.com.cn/record/153542044
P10278
题意
给定 个柱子的坐标,保证它们组成一个邻边互相垂直的多边形,且保证该多边形所有边互不相交。
给定 头牛的起点和终点坐标,保证在多边形上。牛有两种选择:往一边或另一边。牛会选择短的一边。牛经过(包括起点和终点)栅栏时会触碰栅栏。
求每个栅栏被触碰次数。
。
思路
点击查看题解
考察:模拟。
离散化,从一个柱子开始建立多边形,即求出每个点的相邻顶点。
对于每头牛,分别求出起点和终点最近的两个柱子。破环为链,使用前缀和求出求出环上两种路径的长度,选择短的一条。
使用差分标记被触碰的栅栏。最后还原触碰次数并输出即可。
代码
https://www.luogu.com.cn/record/153949576
P10308
题意
定义一次操作为同时将 中所有元素替换为 。
进行 次单点修改,每次修改后,求出最小操作次数使得操作后与操作前序列 相同。答案对 取模。
。
思路
点击查看题解
考察:思维,数学。
显然对于一次操作,其等价于枚举 。类似于前缀和。
以下默认循环节为最短循环节。
题目即求循环节,考虑求出每一位的循环节后取 。