隐藏页面特效

CF2027D The Endspeaker (Hard Version) 题解

题面

给你一个长度为 n 的数组 a 和一个长度为 m 的数组 b (所有 1i<m 满足 bi>bi+1 )。最初, k 的值是 1 。您的目标是通过重复执行这两种操作中的一种,使数组 a 为空:

  • 1 - 如果 k 的值小于 m ,并且数组 a 不是空的,那么可以将 k 的值增加 1 。这不会产生任何费用。
  • 2 - 从数组 a 中移除一个非空的前缀,使得其总和不超过 bk 。需要花费 mk

你需要最小化操作的总成本,使数组 a 为空。如果无法通过任何操作序列实现,则输出 1 。否则,输出操作的最小总成本,以及产生这个最小成本的操作序列的数目,取模为 109+7

如果在任何一步中选择了不同的操作类型,或在任何一步中删除的前缀大小不同,则认为两个操作序列是不同的。

题解

D1(Easy Version)

题目只要求求出最小总成本,所以考虑 dp,我们根据 bi 的单调性,容易发现选择时对 bi 按顺序对成本进行松弛即可,唯一需要确定的是状态的来源。

考虑什么时候转移是合法的,必然是一个区间和小于 bi 时合法,如果一个区间和小于 bi,有一个较小的区间被这个区间所包含,那么一定是不优的,因此我们尽可能的将区间扩大,找到最大满足区间和小于 bi 的区间,可以枚举左端点或右端点做双指针转移,对每个 bi 转移一次即可。

D2(Hard Version)

在 D1 的条件下,我们需要求出转移的方案数,那么对于我们转移的方式应该枚举右端点,这样才能确定每一次转移后的方案数。

对于一个段 l 转移到 r,若对于某个 bi 能使 l 转移到 r

  • dprdpl>mi 时,将 dpl 的方案数赋值到 dpr 上。

  • dprdpl<mi 时,我们跳过这样的 l

  • dprdpl=mi 时,我们将连续的 l 方案数求和,转移到 dpr 上。

因此,我们可以记录一个 maxx 代表当前区间段 dpl=dpmaxx 可以转移到 dpr 的区间段的右端点,如果正在考虑的 l 小于 maxx,那么可以对这个区间段内满足 dprdpl=mi 的部分求和,可以证明 l 是单调递增的,如果 l 大于 maxx,更新 maxx,方案数替换为下一个合法的区间,令 maxx=l 继续转移。

容易发现,上述操作和双指针无异,时间复杂度 O(nm)

参考代码

复制
#include<bits/stdc++.h> using namespace std; typedef long long ll; const int N = 3e5 + 10, mod = 1e9 + 7; int n, m; ll a[N], b[N]; void solve() { cin >> n >> m; vector<ll> pre(n + 1); for (int i = 1; i <= n; i ++ ) cin >> a[i], pre[i] = pre[i - 1] + a[i]; for (int i = 1; i <= m; i ++ ) cin >> b[i]; vector<ll> dp(n + 1, 1e18), f(n + 1); dp[0] = 0, f[0] = 1; for (int i = 1; i <= m; i ++ ) { ll sum = 0; for (int l = 0, r = 1, maxx = 0; r <= n; r ++ ) { while (pre[r] - pre[l] > b[i]) (sum -= f[l]) %= mod, l ++ ; if (maxx < l) maxx = l, sum = 0; while (maxx < r && dp[maxx] == dp[l]) (sum += f[maxx]) %= mod, maxx ++ ; if (l < r) { if (dp[r] > dp[l] + m - i) dp[r] = dp[l] + m - i, f[r] = sum; else if (dp[r] == dp[l] + m - i) (f[r] += sum) %= mod; } } } if (dp[n] == 1e18) cout << "-1\n"; else cout << dp[n] << ' ' << (f[n] + mod) % mod << '\n'; } int main() { ios::sync_with_stdio(false); cin.tie(0), cout.tie(0); int T = 1; cin >> T; while (T -- ) solve(); return 0; }

__EOF__

本文作者Yip.Chip
本文链接https://www.cnblogs.com/YipChipqwq/p/-/CF2027D.html
关于博主:评论和私信会在第一时间回复。或者直接私信我。
版权声明:本博客所有文章除特别声明外,均采用 BY-NC-SA 许可协议。转载请注明出处!
声援博主:如果您觉得文章对您有帮助,可以点击文章右下角推荐一下。您的鼓励是博主的最大动力!
posted @   YipChip  阅读(23)  评论(0编辑  收藏  举报
相关博文:
阅读排行:
· 单线程的Redis速度为什么快?
· 展开说说关于C#中ORM框架的用法!
· Pantheons:用 TypeScript 打造主流大模型对话的一站式集成库
· SQL Server 2025 AI相关能力初探
· 为什么 退出登录 或 修改密码 无法使 token 失效
点击右上角即可分享
微信分享提示