一本通OJ-划分数列

划分数列

题意

给定一个长度为\(n\)的数列 \(A\),要求划分最少的段数,使得每一段要么单调不降,要么单调不升。

分析

设两个数组

\(up[i]\) 表示以\(i\)结尾单调不降数列起始位置,同理\(down[i]\)表示以\(i\)结尾单调不升数列起始位置。

\(f[i]\)表示以\(i\)结尾的数列最少段数。

则有\(f[i] = min(f[up[i] - 1] + 1, f[down[i] - 1] + 1)\)

代码

#include<bits/stdc++.h>
using namespace std;
int n;
const int N=1e5+7;
int a[N];
int down[N],up[N],f[N];
int main(){
    cin>>n;
    memset(f,0x3f,sizeof f);
    for(int i=1;i<=n;i++) scanf("%d",&a[i]);
    up[1]=1,down[1]=1;
    for(int i=2;i<=n;i++){
        if(a[i-1]<=a[i]) up[i]=up[i-1];
        else up[i]=i;
        if(a[i-1]>=a[i]) down[i]=down[i-1];
        else down[i]=i;
    }
    f[1]=f[0]=0;
    for(int i=1;i<=n;i++){
        f[i]=min(f[up[i]-1]+1,f[down[i]-1]+1);
    }
    printf("%d",f[n]);
    return 0;
}
posted @ 2023-07-25 13:53  Zimo_666  阅读(42)  评论(0编辑  收藏  举报