AtcoderABC309场
发布人:shili8
发布时间:2024-11-08 06:57
阅读次数:0
**AtCoder ABC309 场**
### **D. 数组中的最大子序列**
#### **题目描述**
给定一个长度为 $n$ 的整数数组 $a_1, a_2, ldots, a_n$,其中每个元素都是非负整数。请找出一个长度为 $k$ 的子序列,使得它的和最大。
#### **输入格式**
* 第一行:两个整数 $n$ 和 $m$,分别表示数组 $a_1, a_2, ldots, a_n$ 中元素的数量,以及子序列中允许出现的最大元素个数。
* 第二行:$n$ 个非负整数 $a_1, a_2, ldots, a_n$,表示数组中的每个元素。
#### **输出格式**
*一个整数,表示长度为 $k$ 的子序列的最大和。
#### **样例输入**
53048910
#### **样例输出**
28
### **解决方案**
我们可以使用动态规划来解决这个问题。首先,我们定义一个长度为 $n$ 的数组 `dp`,其中 `dp[i]` 表示以 `a_i` 为结尾的子序列的最大和。
然后,我们遍历每个元素,并根据以下规则更新 `dp`:
* 如果当前元素小于或等于前一个元素,则将其添加到前一个元素所构成的子序列中。
* 否则,将其作为新子序列的开头。
具体来说,我们可以使用以下代码来实现这一点:
cpp#include <iostream> using namespace std; int main() { int n, m; cin >> n >> m; int a[n]; for (int i =0; i < n; i++) { cin >> a[i]; } int dp[m +1][n]; // dp[i][j] 表示以 a[j] 为结尾的子序列中,元素个数为 i 的最大和 for (int j =0; j < n; j++) { dp[1][j] = a[j]; } for (int i =2; i <= m; i++) { int max_sum = -1; for (int j =0; j < n; j++) { if (a[j] > dp[i -1][j]) { dp[i][j] = a[j]; } else { dp[i][j] = dp[i -1][j]; } max_sum = max(max_sum, dp[i][j]); } cout << max_sum << endl; } return0; }
### **注释**
* 我们首先读入两个整数 `n` 和 `m`,分别表示数组中元素的数量和子序列中允许出现的最大元素个数。
* 然后,我们读入长度为 $n$ 的整数数组 `a_1, a_2, ldots, a_n`。
* 我们定义一个长度为 $m +1$ 的二维数组 `dp`,其中 `dp[i][j]` 表示以 `a_j` 为结尾的子序列中,元素个数为 $i$ 的最大和。
* 我们首先将每个元素添加到前一个元素所构成的子序列中,以便 `dp[1][j] = a[j]`。
* 然后,我们遍历每个元素,并根据以下规则更新 `dp`:
* 如果当前元素小于或等于前一个元素,则将其添加到前一个元素所构成的子序列中。
* 否则,将其作为新子序列的开头。
* 最后,我们输出长度为 $k$ 的子序列的最大和。
### **时间复杂度**
*读入两个整数 `n` 和 `m`:$O(1)$*读入长度为 $n$ 的整数数组 `a_1, a_2, ldots, a_n`:$O(n)$* 初始化二维数组 `dp`:$O((m +1) cdot n)$* 遍历每个元素并更新 `dp`:$O(m cdot n)$* 总时间复杂度:$O(n + m cdot n)$### **空间复杂度**
* 使用二维数组 `dp`:$O((m +1) cdot n)$