Loading

Smithing Skill

算法

转化题意,

显然的, 每次操作必定是先锻造再熔毁, 获得 \(2\) 点经验, 并且花费 \(w_i = a_i - b_i\) 个同类型金属, 问题就是说, 如何操作使得操作次数可以最多

首先使用贪心思路, 以 \(w_i\) 为关键字升序排序, 显然的, 在前面的物品一定应该先选择, 并且维护 \(a_i\) 递减, 不递减的都没有用, 这个用单调栈维护即可

有一种朴素的方法是, 对于每一种金属, 都贪心的去按照序列顺序选择, 但是这样不够优秀, 考虑优化

首先, 对于每一种材料, 我们按照贪心的去选, 这样一定是最优秀的

但是这样做, 时间复杂度达到了 \(\mathcal{O} (n \log n + nm)\) , 包过不去的, 那么怎么处理呢?

考虑暴力劣在哪里, 对于每一种金属, 我们都枚举了所有材料, 很显然不优

我们考虑对于每一种武器, 直接枚举所有金属, 这样时间复杂度显然更优, 那么如何来处理呢

发现每一种 \(c_i\) 的本质相同, 只是不能混着用, 注意到我们可以预处理 \(c_i\) 值域的最优解, 这样每次就不用重复处理了

我们可以处理出对于所有 \(c_i\) , 当 \(c_i = x\) 时, 最优的 \(w_i\) 为多少, 即 \(\displaystyle \min_{a_j \leq x} a_j - b_j\) , 记为 \(cost_x\)

那么 \(cost_x\) 是好递推的, 我们只需要先用每一种 \(a_j - b_j\) 更新, 然后类似前缀的做一遍, 这算是一种普遍的 \(\rm{trick}\)

考虑令 \(f_x\) 表示当 \(c_i = x\) 时, 最优的锻造方式, 那么显然的, 有

\[f_x = f_{x - cost_x} + 2 \]

每次读入 \(c_i\) 先用最优情况的 \(w_i\) 把它降到 \(10^6\) 级别即可


写的有点一坨, 重复习一下

题意

nn 个武器, 每个武器有属性 {ci,pi}\{c_i, p_i\} , 表示锻造所需的花费, 熔毁返还的花费
mm 种金属, 每种金属有 gig_i

锻造第 ii 个武器的定义

对于第 jj 种金属, 其当前还剩下 gjg_j 个, 如果 gjcig_j \geq c_i , 可以令 gjgjci+pig_j \gets g_j - c_i + p_i

求最多的锻造次数

根据定义不难发现

贪心做法

每一个武器的花费 wi=cipiw_i = c_i - p_i
按照 wiw_i 排序之后, 单调栈维护 cic_i 递减即可

每一种金属按照排完序之后的顺序依次尽量锻造
复杂度 O(nlogn+nm)\mathcal{O} (n \log n + nm)


考虑优化,
不难发现对于每种金属, 处理的本质是相通的, 考虑对于 \(g_i\) 的值域进行 \(\rm{dp}\)

但是该如何处理?
\(f_i\) 表示 \(g_i = i\) 时对应的最多锻造次数, 并不好直接做, 考虑辅助数组

\(cost_i\) 表示 \(g_i = i\) 时对应的最优 \(w_i\) , 形式的讲就是所有 \(c_i \leq i\)\(\min \{w_i = c_i - p_i \}\)
这个怎么做?

常见处理方式

对于这种求 /\leq / \geq 中的最值
我们可以考虑先赋上单点, 然后扫一遍更新

对于本题, 考虑对于排完序之后的数列, 更新 costci=wicost_{c_i} = w_i , 然后倒序扫一遍更新即可

此事在 雅礼国庆集训 day1 T1 养花 亦有记载

搞完这些, \(f_i\) 转移不难得出

\[f_i \gets f_{i - cost_i} + 2 \]

也就是说每次都用最优解

最后一个问题是 \(g_i\) 非常巨大, 但是不难发现每次读入 \(c_i\) 先用最优情况的 \(w_i\) 把它降到 \(10^6\) 级别即可

代码

状态超级差, 真的不想打

总结

本质相同的问题, 优化要利用这点

\(10^8\) 以上的问题, 观察是否真的需要处理这么多

posted @ 2024-12-05 16:15  Yorg  阅读(16)  评论(0)    收藏  举报