划分数列(ybtoj递推练习题1)

题目描述

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

输入格式

第一行一个整数 。

接下来 n 个数表示数列 。

输出格式

输出最少的划分数。

最开始 没有头绪。。。

后来想到 之前做的LIS。。。

然后就

dw[]数组维护单调不降的序列的起点位置;

up[]数组维护单调不升的序列的起点位置;

这样一来;

f[]数组维护划分的最小序列个数

则有

f[i] = min(f[dw[i] - 1],f[up[i]- 1]);

OK 上代码:

 1 #include <iostream>
 2 #include <cstdio>
 3 #include <algorithm>
 4 #include <climits>
 5 #include <cassert>
 6 #include <cmath>
 7 #include <cstring>
 8 #include <cstdlib>
 9 #include <cctype>
10 #include <utility>
11 #include <set>
12 #include <map>
13 #include <stack>
14 #include <queue>
15 #include <vector>
16 #define int long long
17 #define ll long long
18 #define ull unsigned long long
19 #define re register
20 #define lowbit(x) x & (-x)
21 #define gcd(a,b) _gcd(a,b)
22 #define mid ((l + r) >> 1)
23 #define rep(i,a,b)  for(re int i(a);i <= b;i ++)
24 #define rrep(i,a,b) for(re int i(a);i >= b;i --)
25 using namespace std;
26 inline int read(){
27     re int x = 0,f = 1;
28     re char ch = getchar();
29     while(ch < '0' || ch > '9'){
30         if(ch == '-') f = -1;
31         ch = getchar();
32     }
33     while(ch >= '0' && ch <= '9'){
34         x = (x << 3) + (x << 1) + (ch ^ 48);
35         ch = getchar();
36     }
37     return x * f;
38 }
39 const int M = 1e6 + 5;
40 int dw[M];
41 int up[M];
42 int a[M];
43 int f[M];
44 signed main(){
45     int n = read();
46     rep(i,1,n){
47         a[i] = read();
48     }
49     dw[0] = up[0] = 0;
50     f[0] = 0;
51     f[1] = 1;
52     rep(i,2,n){
53         if(a[i] >= a[i - 1]) dw[i] = dw[i - 1];
54         else dw[i] = i;
55         if(a[i] <= a[i - 1]) up[i] = up[i - 1];
56         else up[i] = i;
57         f[i] = min(f[dw[i] - 1] + 1,f[up[i] - 1] + 1);
58     }
59     cout << f[n] << endl;
60     return 0;
61 }

 

posted @ 2022-08-26 23:41  November&&Rain  阅读(57)  评论(0)    收藏  举报