OpenJudge 2711 合唱队形

题目链接:OpenJudge 2711 合唱队形

题目大意:

题解:
正反各求一次最长上升序列,对每个点取正反两次以该点为最高点的最长上升子序列长度之和(注意该点被取两次,需要减一)即为以该点为最高点的最长合唱队列。

#include <algorithm>
#include <iostream>
using namespace std;
#define N 110

int n, dp1[N], dp2[N], h[N], t1[N], t2[N], len1, len2, ans;

int main() {
    cin >> n;
    for (int i = 1; i <= n; ++i) {
        cin >> h[i];
    }
    dp1[++len1] = h[1];
    t1[1] = 1;
    for (int i = 1; i <= n; ++i) {
        if (dp1[len1] < h[i]) {
            dp1[++len1] = h[i];
            t1[i] = len1;
        } else {
            int p1 = lower_bound(dp1 + 1, dp1 + len1 + 1, h[i]) - dp1;
            dp1[p1] = h[i];
            t1[i] = p1;
        }
    }
    dp2[++len2] = h[n];
    t2[n] = 1;
    for (int i = n; i > 0; --i) {
        if (dp2[len2] < h[i]) {
            dp2[++len2] = h[i];
            t2[i] = len2;
        } else {
            int p2 = lower_bound(dp2 + 1, dp2 + len2 + 1, h[i]) - dp2;
            dp2[p2] = h[i];
            t2[i] = p2;
        }
    }
    for (int i = 1; i <= n; ++i) {
        ans = max(ans, t1[i] + t2[i] - 1);
    }
    cout << n - ans;
    return 0;
}
原文地址:https://www.cnblogs.com/IzumiSagiri/p/15059575.html