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