原题大意
给一串长度为N的序列,问至少将其分成几个子序列,使得每个子序列要么非递增,要么非递减。输出最少子序列的个数。
算法分析
设置类似开关一样的标志,如果开始以非递减序列为真的话,依次检查下一个数字,满足非递减条件就继续,标志依旧为真;不满足条件时,改标志为假,子序列个数加1;然后依次检查下一个数字,如果满足非递增的条件,标志依旧为假,否则再改为真,并且子序列个数加1,如此重复,知道结束。但是有一些注意的地方:
- 要另设一个长度标志len,记录新的子序列的长度,只有在长度大于1并且不符合前面的增减关系时才能增加子序列的个数,否则会多解。
- 如果当前数字和前一个相等时并且len为1时,len不变,直接继续下一次循环。
程序代码
#include <cstdio>
using namespace std;
const int maxn = 1e5+5;
int d[maxn];
int n;
int main(){
//freopen("input.txt", "r", stdin);
while(scanf("%d", &n) == 1){
for(int i = 0; i < n; i++)
scanf("%d", &d[i]);
bool fg1;
if(n == 1)
{
printf("1\n");
continue;
}
int ans = 0;
int len = 1;
for(int i = 1; i < n; i++)
{
if(len == 1)
{
int t = d[i] - d[i-1];
if(t == 0) continue;
else fg1 = (t > 0) ? true: false;
}
if(fg1 == true)
{
if(d[i] >= d[i-1]) len++;
else{
fg1 = false;
if(len > 1){ans++; len = 1;}
}
}
else{
if(d[i] <= d[i-1]) len++;
else{
fg1 = true;
if(len > 1){ans++; len = 1;}
}
}
}
printf("%d\n", ans+1);
}
return 0;
}