一本通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;
}