A
为了避免重复遍历已经被买走的物品,我们引入并查集。
我们定义 fa[x] 表示:“如果我要买第 x 个物品,我实际应该去看的下一个候选物品是谁?”
• 初始状态: fa[x] = x。大家都还没卖出去,我想买 x,我就能买到 x。
• 跳跃机制: 当代码中执行 if (find(j) != j) 时,意味着第 j 个物品已经被买走了。此时通过并查集的路径压缩,find(j) 会瞬间返回 j 后面第一个可能还有货的物品位置!
• 光速越过废墟: 代码中的 j = find(j);。它直接把指针 j 瞬移到了下一个有意义的位置,中间哪怕有十万个已经卖出的物品,也只需 O(1) 的时间直接跳过。
B
由于是加权单向边,因为你不能回头,所以你走任何一条边都不清楚这条边对后续状态的影响是大还是小,换句话说,当你走过一条边权值小的边,你不清楚这条边后续能经过的边的边权值是大还是小,所以考虑dp,由于体力值很小,所以可以开一个30×5e5的二维数组,状态转移为从u能到达的v点向u转移,第p步的时候从v点到u,dp[p][i]表示u点到i点在p个体力值的时候能获得的最大权值
核心转移方程代码:
for(int i=0;i<=30;++i){
for(int j=1;j<=n;++i){
for(auto x:e[j]){
dp[i][j]=max(dp[i][j],dp[i-1][x]+x.w);
}
}
}
C
跟A题一样,没多大差别
D
按照题意模拟即可
E
这题真是抱歉,题目没仔细看一遍。
输出ascii码的和即可
F
对于每种冰棒开一个队列,存这个冰棒的生产时间,对于每个人按到店时间排序,每来一个人,对于他想买的冰棒,不在期限内就pop掉,队列为空或钱不够就把这个人pass掉,买得了就把这个冰棒也pop掉并答案加一。
G
差分序列的引入
处理区间翻转问题,最常用的手段是差分。
定义差分序列
(其中
)。
- 前缀翻转
:改变了
和
的相对状态。在差分序列上,仅体现为
发生翻转。
- 后缀翻转
:改变了
和
的相对状态。在差分序列上,仅体现为 **
发生翻转。 注意:差分序列只能确定
之间的相对关系,无法确定具体的绝对值。要确定整个序列,还需要一个基准值(例如
)。 状态映射 对与长度为
的原序列,我们可以映射到一个长度为
的新序列:
- 差分位:
,共
位。
- 基准位:
(或者
),共
位。 所有的
个差分位,都可以通过一次对应的“前缀翻转”或“后缀翻转”独立地改变状态。 例如:翻转
,只需要执行一次
Prefix Shift(i)。
- 最少操作次数分析
我们发现,原序列的
种状态,一一对应差分向量
的
种取值。
- 差分位
: 每一位
如果目标是
(即
),则必须至少操作一次来产生这个差异。
- 基准位
: 如果目标状态的
,说明相对于初始的“全高能态”,我们需要改变第一位的状态。 - 如果此时已经有某个
被翻转了(比如执行了
Suffix Shift(i+1)),可能已经随之翻转。 - 如果所有
都是
,但
需要是
,则必须执行一次覆盖第一位的操作(如
Prefix Shift(n))。 结论 通过数论与位运算性质推导,该问题可以简化为:
- 状态由
个独立的差分开关和
个整体偏移构成。
- 到达某个状态的最少操作次数,等于该状态下 差分序列中
的个数,但存在一种特殊情况:如果需要翻转
却不改变任何差分位(即目标为全
或全
的特定变换),操作次数会产生偏移。 经过数学归纳,总步数公式为:
H
- 关键性质分析注意题目中的边失效条件:
时边失效。这意味着随着时间
的增加,可用的边只会减少,不会增加。如果按照时间正序处理,我们需要不断从图中删边并重新计算最短路,这在
或
的复杂度下是难以承受的。逆向思维:如果我们从晚到早处理询问(
从大到小),那么随着
的减小,满足
的边会逐渐增加。2. 算法选择:Floyd-Warshall 增量更新由于
,全源最短路通常考虑 Floyd 算法。当我们在图中新增一条边
,其长度为
时,并不需要重新跑一遍
的 Floyd。我们可以通过这条新边来更新所有节点对
的最短距离:
这种增量更新的复杂度仅为
。3. 算法步骤离线处理:将所有询问按照时间
降序排序;将所有边按照承受上限
降序排序。初始化:初始化最短路矩阵
为无穷大,自环为
。双指针遍历:遍历排序后的询问。对于当前询问的时间
:将所有满足
的边加入图中。每加入一条边,执行一次
的动态更新。更新完后,记录当前询问的答案。输出:按照询问的原始顺序输出结果。复杂度分析时间复杂度:排序:
。Floyd 增量更新:总共加
条边,每次
,总计
。在本题中
,对于 1-2 秒的时限来说稍显吃力,但由于很多边可能并不会更新最短路(即代码中 eg[idx].d >= f[u][v] 的剪枝),实际运行效率会很高。空间复杂度:
,主要是存储距离矩阵和询问信息。
I
本题需要分三种情况讨论:
在进行一次循环后,我们可以得到一个新的清醒度num,将num和原清醒度x进行对比。
(1) num<x,则代表每经过一次歌曲循环,清醒度都会减小,那么一定存在多次循环后清醒度满足条件。
(2)num>x,那么每次播放歌曲,都会使清醒度增大。那么能满足条件的清醒度只可能存在于第1次播放,在第1次播放的时候判断即可。
(3)num=x,这个又需要分两种情况进行讨论:第1种情况是原x>k,那么在第1次播放的时候判断即可。第2种情况是x=k,那么我们需要在播放第1次和第2次歌曲去判断,记录符合条件的清醒度持续的最长时间,如果t<n,直接将最长时间与t进行对比,需大于等于t。但是如果t>=n, 那么我们则只需要最长时间大于等于n即可(只要满足此要求,那么在循环多遍后,无论t多大,都能满足)。
J
题目要求我们计算: floor(N / M) % 10007。
因为 N 极大,根本无法用普通数据类型直接表示。我们设 N 除以 (10007 * M) 的商为 q,余数为 R,则有:
N = q * (10007 * M) + R
将其代入题目要求的式子中:
floor( [q * 10007 * M + R] / M ) % 10007
= (q * 10007 + floor(R / M)) % 10007
= floor(R / M) % 10007
核心结论: 我们不需要知道 N 到底多大,只需要求出 N 对 (M * 10007) 取模的结果即可!
在此,我们令基础模数 Mod_base = M * 10007。
三、 核心思维二:扩大 9 倍模数,完美避开逆元
N 是由一段段数字拼接的。假设要在当前数字后拼接 L 个数字 c。
这一段纯数字的值,其实是一个等比数列求和公式:
。
拼接后的新值为:
新值 = 旧值
致命问题: 我们需要在模 Mod_base 意义下计算这个式子。但是式子中有一个“除以 9”。如果输入的 M 是 3 或 9 的倍数,那么 9 在该模数体系下是不存在逆元的,常规的除法取模操作直接失效!
破局神技: 直接将模数扩大 9 倍!
令最终计算模数 MOD = 9 * M * 10007。
我们在这个扩大的 MOD 环境下计算出
的余数。因为
在数学本质上绝对是 9 的倍数,所以我们算出大模数下的余数后,直接在普通整数代码中除以 9,就能得到绝对正确且没有精度损失的等比数列和!
最后得出答案后,由于公式最后一步是 (ans / m)%10007,这个提前扩大的 9 倍误差会被自然而完美地消除。
四、 核心思维三:十进制快速幂处理超长字符串
本题中,重复次数 L 是一个长度可达
的字符串。求
该怎么做?
我们可以从左到右遍历字符串的每一位。
假设当前累计的幂次结果为 pre,读取到字符串下一位数字 d 时,新的幂次结果相当于:
。
为了极速计算 pre^10,采用手动二进制展开的极致优化:
。
这使得我们对每个字符的处理降到了绝对常数级别,摒弃了繁琐的欧拉降幂和高精度比较。
K
为了满足“非递减”条件并求出方案数,我们可以将其转化为完全背包问题的一个变种:
- 物品:所有的完全平方数
,其中
。
- 限制:恰好选出
个物品,总和为
。
定义状态 表示:使用
个盒子,凑出糖果总数为
的方案数。
转移方程:
为了保证非递减,我们有两种思路。最高效的一种是借鉴“整数拆分”的技巧。
考虑到所有物品都是平方数,我们可以枚举当前使用的最小平方数是多少。但更简单的方法是直接套用背包:
设 为可选的正平方数集合。
注意:由于盒子可以放
(
也是平方数),且要求非递减。实际上这等价于:从可选的平方数集合中,选出不超过
个正平方数,使其总和等于
。 剩下的盒子全部填
即可。
但为了方便记录路径,我们采用如下 DP:
:使用了前
种正平方数(
),当前总和为
时,所使用的盒子总数。
为了输出任意一组解:
- 在 DP 转移时,记录
pre[i][j],表示当前状态是从哪个状态转移过来的(或者记录当前选了几个某种平方数)。 - 如果
,说明剩下的
个盒子填
即可。
L
- 题目核心我们需要从长度为
的数组中找到两个数
和
(
),使得它们的按位与(Bitwise AND)结果最大。优先条件:按位与的结果最大。次要条件:若最大值相同,输出下标组合字典序最小的一组(即
越小越好,若
相同则
越小越好)。2. 贪心策略按位与运算的特点是:高位的一位
胜过低位所有的
。例如:二进制
(8) 大于
(7)。为了让结果最大,我们应该从最高位(第 31 位)向最低位(第 0 位)遍历:检查当前所有候选数字中,在这一位为
的数字个数是否
。如果满足:说明最终的最大结果在这一位可以为
。为了保住这个高位的
,我们必须剔除掉所有在这一位为
的数字,剩下的数字进入下一轮筛选。如果不满足(即在这一位为
的数少于 2 个):说明这一位无法通过两个数按位与得到
,我们只能放弃这一位,保留当前所有的候选数字进入下一轮。
全部评论
(0) 回帖