P1091合唱队形

P1091 合唱队形

题意

n位同学站成一排,要求满足所选同学的身高严格单调递增在递减,问最少需要几位同学出列

思路

先正的求一遍LIS,在逆着求一边LIS,最后再求以i(1<=i<=n)为一个转折点求最大的和即为所要求的人(这里要减去1不仅要防止不选还要防止选这一位置俩次),最后在用总数减去这个最大的人数即为所求答案。用贪心加二分的LIS求最长连续子序列,复杂度为o(n).

代码

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
#include<bits/stdc++.h>
using namespace std;
const int maxn=100+10;
int dp[2][maxn];
int a[maxn];
int b[maxn];
int main(){
int n;
cin>>n;
for(int i=1;i<=n;i++) cin>>a[i];
b[1]=a[1];
dp[0][1]=1;
int pos=1;
for(int i=2;i<=n;i++){
if(a[i]>b[pos]) {
pos++;
dp[0][i]=pos;
b[pos]=a[i];
}
else {
b[lower_bound(b+1,b+pos+1,a[i])-b]=a[i];
dp[0][i]=pos;
}
}
b[1]=a[n];
dp[1][1]=1;
pos=1;
for(int i=n-1,j=2;i>=1;i--,j++){
if(a[i]>b[pos]) {
pos++;
dp[1][j]=pos;
b[pos]=a[i];
}
else {
b[lower_bound(b+1,b+pos+1,a[i])-b]=a[i];
dp[1][j]=pos;
}
}
int maxx=0;
for(int i=1;i<=n;i++){
maxx=max(maxx,dp[0][i]+dp[1][n-i+1]-1);
}
printf("%d\n",n-maxx);
}