题面:
题目描述
给定一个长度为 n 的数列 ,要求划分最少的段数,使得每一段要么单调不降,要么单调不升。
输入格式
第一行一个整数 n 。
接下来 n 个数表示数列 。
输出格式
输出最少的划分数。
样例
样例输入 1
6
1 2 3 2 2 1
样例输出 1
2
样例输入 2
9
1 2 1 2 1 2 1 2 1
样例输出 2
5
样例输入 3
7
1 2 3 2 1 999999999 1000000000
样例输出 3
3
题解
博主使用的是最好理解的模拟做法
思路:
用一次循环扫描整个数列,记录当前数列段的升降状态、个数和该序列的最后一个数,如果正在处理的数不满足当前数列的升降状态,则将数列分段,重新记录数据,直到结束。
具体见代码,注释十分详细
代码:
#include<iostream>
#include<cstdio>
using namespace std;
int a[100005];
int main() {
int n;
cin>>n;
for(int i=1; i<=n; ++i) scanf("%d",&a[i]);
int i_=0,zt,sum(1),last; //i_用来记录当前所在分段中有几个数
//zt用来记录当前数列段的升降状态
//last用来记录当前序列的最后一个数
//sum用来记录当前分段总数
for(int i=1; i<=n; ++i) {
if(i_==0){ //如果是新分段,则将分段初始化,并记录当前数字
last=a[i];
i_++;
continue;
}
if(i_==1) //如果当前分段只有一个数,则在读入第二个数时确定当前分段的升降状态
if(a[i]>a[i-1]) zt=1; //判断升降状态并记录
else zt=0;
if(zt==1&&a[i]<last&&i_>=2){ //如果正在处理的数不符合上一个分段的升降状态(在不下降序列中)
sum++; //分段数+1
last=a[i]; //初始化新分段
i_=0; //初始化新分段
}
if(zt==0&&a[i]>last&&i_>=2){ //如果正在处理的数不符合上一个分段的升降状态(在不上升序列中)
sum++; //分段数+1
last=a[i]; //初始化新分段
i_=0; //初始化新分段
}
i_++; //当前分段内的数字数量+1
last=a[i]; //更新该分段最后一个数
}
cout<<sum;
}