一、排序子序列划分
题目解析
给定一个数组,判断该数组最少可以划分为多少个排序子序列。这里的排序子序列定义为非递增或非递减的连续子序列。
例如:1 2 3 2 2 1 可以划分为 1 2 3(非递减)和 2 2 1(非递增)两个部分。
算法思路
这道题的核心在于贪心策略。我们从头遍历数组,尽可能延长当前的排序子序列。
处理逻辑:
- 初始状态:从下标 0 开始,我们需要确定当前是处于非递增还是非递减趋势。
- 相等元素:如果遇到数值相同的区域,这段相等的序列既可以接在前面的非递增序列后,也可以接在非递减序列后。因此,遇到相等时,我们可以暂时跳过,继续向后寻找趋势变化的点。
- 边界情况:
- 如果数组开头就是相等序列,直接跳过即可,因为它们能融入后续确定的序列中。
- 对于最后一个位置,如果它无法与前一个序列合并,则单独作为一个新的子序列计数。
注意点:
在代码实现时,需要特别注意数组越界问题。比较 arr[i] 和 arr[i+1] 前,务必确保 i+1 不超出范围。
代码实现
#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 - 1) {
ret++;
break;
}
if (arr[i] < arr[i + 1]) { // 发现上升趋势,标记为非递减
while (i + 1 < 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;
;
}


