LibreOJ 2612 花匠

题目链接:LibreOJ 2612 花匠

题目大意:

题解:
本题是求最长抖动子序列。
\(dp[i][0/1]\)表示判断到第\(i\)位且第\(i\)位为下降/上升结尾的情况下最长抖动序列的长度。

分以下三种情况讨论:

  1. \(h[i]=h[i-1]\),则第\(i\)位可以替换掉第\(i-1\)位;
  2. \(h[i]>h[i-1]\),则第\(i\)位为下降结尾的情况可以继承第\(i-1\)位为下降结尾的情况,因为在第\(i\)位之后只有比第\(i\)位大的以上升结尾的序列才会用到第\(i\)位以下降结尾的序列,又因为\(h[i]>h[i-1]\),则其一定比第\(i-1\)位大,可以放在第\(i-1\)位下降结尾的序列后;
    \(i\)位为上升结尾的情况可分为两种:
    (1) 第\(i\)位可以替换掉第\(i-1\)位继承其上升结尾的情况;
    (2) 第\(i\)位可以放在第\(i-1\)位下降结尾的序列后,序列长度加一;
  3. \(h[i]<h[i-1]\),则第\(i\)位为上升结尾的情况可以继承第\(i-1\)位为上升结尾的情况,因为在第\(i\)位之后只有比第\(i\)位小的以下降结尾的序列才会用到第\(i\)位以上升结尾的序列,又因为\(h[i]<h[i-1]\),则其一定比第\(i-1\)位小,可以放在第\(i-1\)位上升结尾的序列后;
    \(i\)位为下降结尾的情况可分为两种:
    (1) 第\(i\)位可以替换掉第\(i-1\)位继承其下降结尾的情况;
    (2) 第\(i\)位可以放在第\(i-1\)位上升结尾的序列后,序列长度加一。

状态转移方程为:

\[\left\{\begin{aligned}dp[i][0]=dp[i-1][0]\\dp[i][1]=dp[i-1][1]\end{aligned}\right.,h[i]=h[i-1] \]

\[\left\{\begin{aligned}dp[i][0]&=dp[i-1][0]\\dp[i][1]&=max\{dp[i-1][1],dp[i-1][0] + 1\}\end{aligned}\right.,h[i]>h[i-1] \]

\[\left\{\begin{aligned}dp[i][0]&=max\{dp[i-1][0],dp[i-1][1]+1\}\\dp[i][1]&=dp[i-1][1]\end{aligned}\right.,h[i]<h[i-1] \]

#include <iostream>
using namespace std;

int h[2000010], n, dp[2000010][2];

int main() {
    cin >> n;
    for (int i = 1; i <= n; ++i) {
        cin >> h[i];
    }
    dp[1][0] = dp[1][1] = 1;
    for (int i = 2; i <= n; ++i) {
        dp[i][0] = dp[i - 1][0], dp[i][1] = dp[i - 1][1];
        if (h[i] > h[i - 1]) {
            dp[i][1] = max(dp[i][1], dp[i - 1][0] + 1);
        }
        if (h[i] < h[i - 1]) {
            dp[i][0] = max(dp[i][0], dp[i - 1][1] + 1);
        }
    }
    cout << max(dp[n][0], dp[n][1]);
    return 0;
}
posted @ 2021-07-27 00:02  ZZHHOOUU  阅读(26)  评论(0编辑  收藏  举报