1 条题解
-
0
题目分析
我们需要构造一个长度为 的整数数组 ,满足:
- 相邻元素异号:(正负交替)
- 所有长度 ≥ 2 的子数组和为正
- 字典序最小:在所有满足条件的数组中, 的字典序最小
第一步:符号确定
由条件 1,数组必须正负交替。我们可以假设 (若 则整体取反后绝对值序列不变,但符号模式可能影响子数组和,实际上最小化绝对值序列时 应为负)。
因此:
- 奇数下标()为负数
- 偶数下标()为正数
且所有元素均非零。
第二步:正数绝对值下界推导
引理 1:任何正数 必须满足 。
证明:考虑 或 时,正数只有一个相邻负数。取长度为 的子数组 (或 ),该负数绝对值至少为 (因为是整数非零),所以正数必须至少为 才能保证和为正。
引理 2:若正数位于中间(),则必须满足 。
证明:考虑子数组 。由于 和 都是负数,其绝对值至少为 ,所以:
$$a_{i-1} + a_i + a_{i+1} \le (-1) + a_i + (-1) = a_i - 2 $$因为子数组和必须为正(至少为 ),所以:
因此:
- 两端的正数(仅当 为偶数时,最后一个元素 是正数)可以取
- 中间的正数(左侧和右侧都有负数)必须取
第三步:贪心构造
为了使得 字典序最小,我们从左到右贪心地取尽可能小的绝对值。
- 最小可取 (负数),所以
- 对于偶数下标 (正数):
- 若 (中间的正数),由引理 2,最小取
- 若 且 为偶数(最后一个元素是正数),由引理 1,最小取
- 对于奇数下标 (负数),最小绝对值可取 ,所以
构造结果:
$$a_i = \begin{cases} -1, & i \text{ 为奇数} \\ 3, & i \text{ 为偶数且 } 2 \le i \le n-1 \\ 2, & i = n \text{ 且 } n \text{ 为偶数} \end{cases} $$
第四步:验证数组是“好”的
条件 1:符号交替 ✓
条件 2(所有长度 的子数组和为正):
- 长度为 2:由一个正数()和一个负数()组成,和 ✓
- 长度为 3:有两种情况:
- 模式 :和为 ✓
- 模式 或 等:两个正数()和一个负数(),和 ✓
- 长度 :至少有 个正数(每个 ),至多有 个负数(每个 ),因此:$$\text{和} \ge 2 \cdot \left\lfloor \frac{k}{2} \right\rfloor - 1 \cdot \left\lceil \frac{k}{2} \right\rceil $$当 为偶数时:$\ge 2 \cdot \frac{k}{2} - \frac{k}{2} = \frac{k}{2} \ge 2$ 当 为奇数时:$\ge 2 \cdot \frac{k-1}{2} - \frac{k+1}{2} = \frac{k-3}{2} \ge \frac{1}{2}$,由于是整数, ✓
因此所有子数组和为正。
第五步:最优性证明
构造过程是贪心的:每个位置上我们都取了满足所有约束的最小可能绝对值。由于约束只依赖于之前的位置(左侧子数组)以及相邻关系,贪心选择不会影响后续位置的可行性(可通过归纳法证明)。因此,得到的 在所有好数组中字典序最小。
第六步:示例
构造结果 绝对值序列 2 3 4 5 6 注意:对于 ,(中间正数)而非 ,因为 时 ( 成立),所以取 。
C++ 实现
#include <iostream> using namespace std; int main() { ios::sync_with_stdio(false); cin.tie(nullptr); int t; cin >> t; while (t--) { int n; cin >> n; for (int i = 1; i <= n; i++) { if (i % 2 == 1) { // 奇数下标:填 -1 cout << "-1"; } else { // 偶数下标(正数) if (i == n && n % 2 == 0) { // 最后一个元素是正数(n 为偶数时) cout << "2"; } else { // 中间的正数 cout << "3"; } } if (i < n) cout << " "; } cout << "\n"; } return 0; }
- 1
信息
- ID
- 7042
- 时间
- 1000ms
- 内存
- 256MiB
- 难度
- 3
- 标签
- 递交数
- 3
- 已通过
- 1
- 上传者