1 条题解
-
0
题目解析
问题描述
给定一个长度为 的数组 ,定义“美丽数组”为:对于所有 ,都有 。
我们可以进行操作:选择相邻的两个数 ,将它们替换为一个数 ,其中 可以是任意整数。
问最少需要多少次操作才能使数组变得美丽?如果不可能,输出 。
解题思路
第一步:检查是否已经美丽
如果原数组已经满足 对所有 成立,那么答案为 。
第二步:检查是否存在局部极值
局部极大值:存在位置 使得
局部极小值:存在位置 使得如果存在这样的极值点,我们可以在 一次操作 内使数组变得美丽。
证明(以局部极大值为例): 假设 (另一种情况对称处理)。
当前序列为:$\dots, a_{i-2}, a_{i-1}, a_i, a_{i+1}, a_{i+2}, \dots$
我们选择操作相邻的 ,令 ,替换后序列变为:
此时:
- 与原来相比,不会变得更差(因为 介于 和 之间或相等)
- 保持不变
- 新产生的相邻对 的差为
所以一次操作即可得到美丽数组。
第三步:没有局部极值的情况
如果没有局部极值,意味着数组是 单调 的(严格递增或严格递减)。
此时,无论我们如何操作,都无法使任意相邻元素的差的绝对值 。原因:
考虑操作替换 为 ,新的相邻对为 和 。
由于单调性, 且 。
因此相邻元素的差不会减小,无法满足 的条件。
算法步骤
- 检查是否已经美丽:遍历 从 到 ,如果存在 ,输出
- 检查是否存在局部极值:遍历 从 到 ,如果 或 ,输出
- 否则输出
时间复杂度:
代码注释
void solve() { int n; cin >> n; vector<int> a(n); for (int i = 0; i < n; i++) cin >> a[i]; // 检查是否已经美丽 for (int i = 1; i < n; i++) { if (abs(a[i - 1] - a[i]) <= 1) { cout << 0 << endl; return; } } // 检查是否存在局部极值 for (int i = 1; i + 1 < n; i++) { if (a[i - 1] < a[i] && a[i] > a[i + 1]) { // 局部极大值 cout << 1 << endl; return; } if (a[i - 1] > a[i] && a[i] < a[i + 1]) { // 局部极小值 cout << 1 << endl; return; } } // 单调数组,无解 cout << -1 << endl; }
总结
情况 答案 已经美丽 存在局部极值 单调数组
- 1
信息
- ID
- 6346
- 时间
- 1000ms
- 内存
- 256MiB
- 难度
- 2
- 标签
- 递交数
- 1
- 已通过
- 1
- 上传者