题面

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

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

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

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

题解

D1(Easy Version)

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

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

D2(Hard Version)

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

对于一个段 \(l\) 转移到 \(r\),若对于某个 \(b_i\) 能使 \(l\) 转移到 \(r\):

  • 当 \(dp_r - dp_l > m - i\) 时,将 \(dp_l\) 的方案数赋值到 \(dp_r\) 上。

  • 当 \(dp_r - dp_l < m - i\) 时,我们跳过这样的 \(l\)。

  • 当 \(dp_r - dp_l = m - i\) 时,我们将连续的 \(l\) 方案数求和,转移到 \(dp_r\) 上。

因此,我们可以记录一个 \(maxx\) 代表当前区间段 \(dp_l = dp_{maxx}\) 可以转移到 \(dp_r\) 的区间段的右端点,如果正在考虑的 \(l\) 小于 \(maxx\),那么可以对这个区间段内满足 \(dp_r - dp_l = m - i\) 的部分求和,可以证明 \(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;
}

CF2027D The Endspeaker (Hard Version) 题解的更多相关文章

  1. Codeforces 1196D2 RGB Substring (Hard version) 题解

    题面 \(q\) 个询问,每个询问给出一个字符串 \(s\),要你在 \(s\) 中用最小替换得到无穷字符串 RGBRGBRGB... 的长度为定值 \(k\) 的子串. 题解 一眼看过去可能是编辑距 ...

  2. CF1157C1-Increasing Subsequence (easy version)题解

    原题地址 题目大意:

  3. Hdoj 2501.Tiling_easy version 题解

    Problem Description 有一个大小是 2 x n 的网格,现在需要用2种规格的骨牌铺满,骨牌规格分别是 2 x 1 和 2 x 2,请计算一共有多少种铺设的方法. Input 输入的第 ...

  4. Palindromes _easy version 题解

    “回文串”是一个正读和反读都一样的字符串,比如“level”或者“noon”等等就是回文串.请写一个程序判断读入的字符串是否是“回文”. Input输入包含多个测试实例,输入数据的第一行是一个正整数n ...

  5. CF1203D2 Remove the Substring (hard version) 题解

    这题初赛让我白给了6分,于是我决定回来解决一下它. 说实话,看原题题面和看CCF代码真是两种完全不同的感受…… ------------思路分析: 把$s$串删去一部分之后,会把$s$串分成两部分,当 ...

  6. UVA12558 Egyptian Fractions (HARD version) (埃及分数,迭代加深搜索)

    UVA12558 Egyptian Fractions (HARD version) 题解 迭代加深搜索,适用于无上界的搜索.每次在一个限定范围中搜索,如果无解再进一步扩大查找范围. 本题中没有分数个 ...

  7. uva12558 Egyptian Fractions (HARD version)(迭代深搜)

    Egyptian Fractions (HARD version) 题解:迭代深搜模板题,因为最小个数,以此为乐观估价函数来迭代深搜,就可以了. #include<cstdio> #inc ...

  8. Codeforces Round #617 (Div. 3) 题解

    又是隔了一年才来补题的我 A.B水题就不用说了 C - Yet Another Walking Robot C题我居然卡了一会,最后决定用map水,结果出来看了看题解,居然真的是map...没想到会出 ...

  9. Codeforces Round #575 (Div. 3)

    本蒟蒻已经掉到灰名了(菜到落泪),希望这次打完能重回绿名吧...... 这次赛中A了三题 下面是本蒟蒻的题解 A.Three Piles of Candies 这题没啥好说的,相加除2就完事了 #in ...

  10. Codeforces Round #581(Div. 2)

    Codeforces Round #581(Div. 2) CF 1204 A. BowWow and the Timetable 题解:发现,$4$的幂次的二进制就是一个$1$后面跟偶数个$0$. ...

随机推荐

  1. Linux firewalld 的用法

    大乌龙事件之防火墙作祟: 在我的初始化环境中 selinux.iptables.firewalld 是关闭的, 莫名的firewalld 是没有关闭的这是我在安装完docker后一段时间后部署jenk ...

  2. OIDC – 关于 SAML 和 ADFS

    前言 最近听朋友说, 正在使用 ADFS 做 SSO, 哎哟. 我都是用 OIDC 做的, 这个 ADFS 是啥? 没听过. 于是搜索了一下, 这里先做一个小记入. ADFS 介绍 参考: stack ...

  3. Asp.net Core 学习笔记 Azure Storage

    更新: 2021-07-22 使用 Azure storage 以后, 还要解决一个 url 的问题. 文件自然是通过我们的 domain 来访问才合理丫. 这个是 azure 的 url : htt ...

  4. OData – How It Work

    前言 OData 是很冷门的东西, 用的人少, 开发的人少, 文档自然也少的可怜. 如果真的想用它, 多少要对它机制有点了解. 这样遇到 bug, 想扩展的时候才不至于完全没有路. 主要参考: ODa ...

  5. 系统编程-进程-当fork遇到管道,可能碰撞出什么?

    第一部分 1. 直接上代码 #include <stdio.h> #include <unistd.h> #include <stdlib.h> int globv ...

  6. 【赵渝强老师】Weblogic域和域的组成

    一.什么是Weblogic WebLogic是美国Oracle公司出品的一个application server,确切的说是一个基于Java EE架构的中间件,WebLogic是用于开发.集成.部署和 ...

  7. Spring技术书的代码资源下载

    我是清华社编辑,这些资源获得作者授权,免费提供给读者个人学习使用.禁止任何形式的商用. 二维码用微信扫,按提示填写你的邮箱,转到电脑上打开邮箱下载.清华国企网盘,比较快速.安全.放心下载. 百度网盘链 ...

  8. android启动时间测试

    需要对比基线测试的情况: Kernel log: adb shell dmesg Event log: adb shell logcat –b events Logcat log: adb shell ...

  9. 墨天轮访谈 | 阿里云捷熙:AnalyticDB,人人可用的数据分析服务

    分享嘉宾:李婧玮(捷熙) 阿里云数据库资深产品经理 整理:墨天轮社区 导读 大家好,我是来自阿里云的捷熙.AnalyticDB是融合数据库.大数据技术于一体的云原生企业级数据仓库平台,今天我为大家带来 ...

  10. C#轻松实现Modbus通信

    1.前言 大家好!我是付工.前面给大家介绍了一系列关于RS485与Modbus的知识. 终于有人把RS485说清楚了终于有人把Modbus说明白了通透!终于把ModbusRTU弄明白了这样看来,Mod ...