一、排序子序列
题目解析
所谓排序子序列,是指数组中一段连续的元素,它们要么是非递增的,要么是非递减的。给定一个数组,我们需要判断它最少可以划分为多少个这样的排序子序列。
例如:1 2 3 2 2 1 可以划分为 1 2 3 和 2 2 1 两个排序子序列。
算法思路
这道题的核心在于如何贪心地确定分割点。
暴力解法 从索引 0 开始遍历,寻找一段满足条件的连续子序列,直到条件不再满足(即发现不单调),此时计数加一并结束当前段;接着从该位置继续向后寻找下一段。
贪心优化 当遇到数值相同的区域时,由于非递增或非递减都允许相等元素存在,这段相等的序列既可以归入前一段,也可以归入后一段。因此,在遍历时遇到相等值,直接跳过即可,无需立即决定归属。
这里有两个边界情况需要注意:
- 开头相等:如果数组起始位置就是相等序列,无法判断后续是递增还是递减。处理策略是直接跳过这些相等元素,因为它们总能被合并到后续的单调序列中。
- 结尾元素:如果最后一个元素无法与前一段组成单调序列,则它单独构成一个子序列。
代码实现
#include <iostream>
using namespace std;
const int N = 1e5 + 10;
int arr[N];
int n;
int main() {
cin >> n;
for (int i = 0; i < n; i++) cin >> arr[i];
int ret = 0;
for (int i = 0; i < n; i++) {
if (i == n - ) {
ret++;
;
}
(arr[i] < arr[i + ]) {
(i < n && arr[i] <= arr[i + ]) i++;
ret++;
} (arr[i] > arr[i + ]) {
(i < n && arr[i] >= arr[i + ]) i++;
ret++;
} {
(i < n && arr[i] == arr[i + ]) i++;
}
}
cout << ret << endl;
;
}


