题目描述
给定一个长度为 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 }
标签:练习题,ch,ybtoj,long,re,dw,include,递推,define From: https://www.cnblogs.com/Eruption/p/16629607.html