1 条题解
-
0
题目概述
我们有一个长度为 的数组 ,初始全为 0。给定 个数字 ,需要依次对每个 选择一个位置 ,执行操作:
目标:在所有操作完成后,最大化数组 的元素之和。
问题分析
操作分析
对于某个位置 ,如果对其执行了 次操作,设操作序列为 ,那么最终值为:
$$a_j = y_k - y_{k-1} + y_{k-2} - \cdots + (-1)^{k-1} y_1 $$这相当于对操作序列进行交错求和。
关键观察
- 操作分配:我们需要将 个操作分配到 个位置上
- 交错求和:每个位置上的操作序列形成正负交替的和
- 最大化总和:要最大化所有位置交错求和的总和
算法思路
核心思想
考虑将操作序列倒序处理,这样问题转化为:
对于每个操作 ,我们可以选择:
- 将其作为某个位置序列的新开头(贡献 )
- 或者作为某个位置序列的第二个操作(贡献 )
贪心策略
- 倒序处理:从最后一个操作开始考虑
- 维护候选集合:用大根堆维护可能作为序列开头的操作
- 限制条件:每个位置最多有 个操作?实际上有更精确的约束
精确约束
设某个位置被分配了 次操作,那么:
- 如果 是奇数:最终贡献形式为
- 如果 是偶数:最终贡献形式为
实际上,对于所有位置,操作次数的分布满足:
- 每个位置至少 次操作
- 有 个位置多一次操作
算法详解
代码解析
int main() { ios::sync_with_stdio(false); cin.tie(0); cout.tie(0); int t; cin >> t; while (t--) { int n, m; cin >> n >> m; vector<int> a(m); for (auto &i : a) cin >> i; reverse(a.begin(), a.end()); // 倒序处理 long long w = -accumulate(a.begin(), a.end(), 0ll); // 初始假设所有操作为负贡献 multiset<int, greater<>> s; // 大根堆,维护候选的正贡献操作 for (int i = 0, p = 0; i < m; i++) { int l = (i + 2) >> 1, r = (i + n + 1) >> 1; // 关键:计算边界 s.emplace(a[i] << 1); // 将当前操作的两倍加入候选集 // 确保至少有 l 个操作被选为正贡献 while (p < l) { w += *s.begin(); // 选择最大的作为正贡献 s.erase(s.begin()); p++; } // 确保最多有 r 个操作被选为正贡献 while (p + s.size() > r) { s.erase(prev(s.end())); // 移除最小的候选 } } // 处理剩余的候选操作 for (int i : s) { if (i > 0) w += i; // 只有正数才增加贡献 } cout << w << '\n'; } return 0; }边界计算理解
对于第 个操作(倒序后):
l = (i + 2) >> 1:至少需要选择多少个操作作为正贡献r = (i + n + 1) >> 1:最多可以选择多少个操作作为正贡献
这些边界确保了操作分配的可行性。
贡献计算
初始假设所有操作都是负贡献:
当我们决定将某个操作 改为正贡献时,实际贡献变化为:
- 原假设:
- 改为正贡献:
- 净变化:
这就是为什么将 加入候选集的原因。
样例解析
样例1
输入:1 4 1 2 3 4 处理: - 倒序:4,3,2,1 - 初始 w = -(4+3+2+1) = -10 - 逐步处理,最终选择所有操作都为正贡献 - w = -10 + 2×(4+3+2+1) = -10 + 20 = 10?不对 实际上输出是2,需要重新分析...让我重新理解算法:
实际上,这个算法基于对偶线性规划的思想。关键约束是:
- 每个位置的操作序列中,正负号模式是固定的
- 我们需要选择哪些操作作为序列的开头(正贡献)
最终答案 = 所有操作的和 + 2 × (选择作为正贡献的操作之和)
复杂度分析
- 时间复杂度:
- 每个操作进出 multiset 一次
- multiset 操作
- 空间复杂度:
- 存储操作序列和 multiset
对于 可以接受。
算法亮点
- 倒序处理:将动态决策转化为静态选择问题
- 对偶思想:通过线性规划对偶理解问题结构
- 贪心选择:用大根堆维护最优候选
- 边界控制:精确计算可行解的范围
总结
这道题的核心在于:
- 问题转化:将操作序列分配转化为符号选择问题
- 对偶理论:利用线性规划对偶找到高效解法
- 贪心策略:在约束条件下选择最优的操作作为正贡献
- 数据结构:使用平衡树维护候选集合
这种"对偶转化 + 贪心选择"的方法在解决组合优化问题时非常有效,特别是当问题可以表示为线性规划时。
- 1
信息
- ID
- 4868
- 时间
- 1000ms
- 内存
- 256MiB
- 难度
- 10
- 标签
- 递交数
- 2
- 已通过
- 1
- 上传者