1 条题解
-
0
「PA 2020」Punkty rankingowe 题解
算法思路
本题使用构造性算法和前缀和性质来解决序列还原问题。核心观察是最大子段和序列必须满足特定的单调性和可加性条件。
关键数学性质
1. 前缀和定义
设 为前 场比赛的 rating 变化总和,则:
2. 必要条件
对于任意 ,最大 项和 必须满足:
for (int i = 1; i <= n; i++) { for (int j = 1; j < i; j++) if (a[i] > a[j] + a[i - j]) { cout << "NIE\n"; return 0; } }
数学解释: 对于所有
3. 充分构造
当上述条件满足时,可以直接构造解:
for (int i = 1; i <= n; i++) cout << a[i] - a[i - 1] << " \n"[i == n];
其中 ,因此第 项的变化量为
算法正确性证明
必要性证明
如果存在 使得 ,则矛盾:
- 考虑长度为 的最大子段,可以将其分割为长度为 和 的两段
- 这两段的和最多为 ,矛盾于 是最大和
充分性证明
当 对所有 成立时,构造的序列满足:
- 前 项的和恰好为
- 任意连续 项的和不超过
代码解析
输入处理
int n; cin >> n; for (int i = 1; i <= n; i++) cin >> a[i];
可行性检查
for (int i = 1; i <= n; i++) { for (int j = 1; j < i; j++) if (a[i] > a[j] + a[i - j]) { cout << "NIE\n"; return 0; } }
构造输出
cout << "TAK\n"; cout << n << "\n"; for (int i = 1; i <= n; i++) cout << a[i] - a[i - 1] << " \n"[i == n];
复杂度分析
- 时间复杂度:,对于 完全可行
- 空间复杂度:
- 1
信息
- ID
- 3339
- 时间
- 1000ms
- 内存
- 256MiB
- 难度
- 10
- 标签
- 递交数
- 1
- 已通过
- 1
- 上传者