题目链接: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;
}