题解:洛谷 AT_abc468_a Maximal Value
【题目来源】
洛谷:AT_abc468_a [ABC468A] Maximal Value
【题目描述】
You are given an integer sequence of length \(N\): \(A=(A_1,A_2,\ldots,A_N)\).
Find the number of integers \(i\) between \(1\) and \(N-2\) (inclusive) satisfying \(A_i < A_{i+1} > A_{i+2}\).
给定一个长度为 \(N\) 的整数序列:\(A=(A_1,A_2,\ldots,A_N)\)。
求满足 \(A_i < A_{i+1} > A_{i+2}\) 的、介于 \(1\) 和 \(N-2\)(含)之间的整数 \(i\) 的个数。
【输入】
The input is given from Standard Input in the following format:
\(N\)
\(A_1\) \(A_2\) \(\ldots\) \(A_N\)
【输出】
Output the answer.
【输入样例】
6
3 1 4 1 5 2
【输出样例】
2
【核心思想】
-
问题分析:给定长度为 \(N\) 的序列 \(A\),统计满足 \(A_i < A_{i+1} > A_{i+2}\) 的位置 \(i\)(\(1 \leq i \leq N-2\))的个数。这是一个线性扫描 + 局部极值判定问题,核心在于遍历每个连续三元组并检查是否为"峰"形结构。
-
算法选择:
- 线性扫描:遍历 \(i\) 从 \(2\) 到 \(N-1\)(对应三元组的中间位置),检查是否满足 \(A_{i-1} < A_i\) 且 \(A_i > A_{i+1}\)
-
关键步骤:
- 读入数据:读取 \(N\) 和数组 \(A[1..N]\)
- 遍历判定(\(i\) 从 \(2\) 到 \(N-1\)):
- 若 \(A_i > A_{i-1}\) 且 \(A_i > A_{i+1}\):\(ans \leftarrow ans + 1\)
- 输出结果:\(ans\)
-
时间/空间复杂度:
- 时间复杂度:\(O(N)\),单次线性遍历
- 空间复杂度:\(O(N)\),存储数组(可优化为 \(O(1)\) 滚动变量)
-
局部极值判定的核心思想:
- 三元组模式识别:\(A_i < A_{i+1} > A_{i+2}\) 描述了一个"先升后降"的局部极大值(峰)。遍历每个可能的中间位置 \(i+1\),检查其是否同时大于左右邻居
- 索引对应关系:题目要求统计满足条件的 \(i\)(\(1 \leq i \leq N-2\)),对应数组下标为 \(i+1\) 作为中间元素。代码中遍历 \(i\) 从 \(2\) 到 \(N-1\),检查 \(A[i-1] < A[i] > A[i+1]\),等价于统计满足条件的 \(i-1\)
- 严格不等式:题目使用严格小于和严格大于,因此相等的情况不计入。代码中的
>和<已满足严格性 - 在线处理可能性:由于每次只用到当前元素和左右相邻元素,可以用三个变量滚动存储,将空间优化到 \(O(1)\)
- 适用于基础序列模式识别、局部特征统计类入门问题
【算法标签】
模拟
【代码详解】
#include <bits/stdc++.h>
using namespace std;
const int N = 105; // 定义数组最大容量为105,满足N的数据范围
int n, ans; // n为序列长度,ans记录满足条件的"峰"的个数
int a[N]; // a数组存储长度为N的整数序列
int main()
{
cin >> n; // 读入序列长度N
for (int i = 1; i <= n; i++) // 读入N个整数
cin >> a[i];
for (int i = 2; i < n; i++) // 遍历序列中每个可能作为"峰"的位置(第2个到第n-1个元素)
if (a[i] > a[i - 1] && a[i] > a[i + 1]) // 判断当前元素是否同时大于左右相邻元素(严格大于左边且严格大于右边)
ans++; // 找到一个满足A_{i-1} < A_i > A_{i+1}的"峰",计数加1
cout << ans << endl; // 输出满足条件的整数i的个数
return 0;
}
【运行结果】
6
3 1 4 1 5 2
2
浙公网安备 33010602011771号