P1091合唱队列[线性DP]
作者:互联网
思路:线性DP
对于原序列求满足
t
1
<
⋅
⋅
⋅
<
t
i
<
t
i
+
1
>
t
i
+
2
>
⋅
⋅
⋅
>
t
k
(
1
<
=
i
<
=
k
)
t_1<···<t_i<t_{i+1}>t_{i+2}>···>t_k(1<=i<=k)
t1<⋅⋅⋅<ti<ti+1>ti+2>⋅⋅⋅>tk(1<=i<=k)的最长子序列
我们将这个关系式拆成两部分来看,即
t
1
<
⋅
⋅
⋅
<
t
i
<
t
i
+
1
t_1<···<t_i<t_{i+1}
t1<⋅⋅⋅<ti<ti+1,和
t
i
+
1
>
t
i
+
2
>
⋅
⋅
⋅
>
t
k
t_{i+1}>t_{i+2}>···>t_k
ti+1>ti+2>⋅⋅⋅>tk
显然我们容易想到,对于每个
t
i
+
1
t_{i+1}
ti+1我们可以正着看求其最长上升子序列
d
p
1
[
i
+
1
]
dp1[i+1]
dp1[i+1]和倒着看求其最长上升子序列
d
p
2
[
i
+
1
]
dp2[i+1]
dp2[i+1],那么对于整个序列来说,我们要求的结果就是
d
p
1
[
i
+
1
]
+
d
p
2
[
i
+
1
]
+
1
dp1[i+1]+dp2[i+1]+1
dp1[i+1]+dp2[i+1]+1,
对每个
t
i
+
1
t_{i+1}
ti+1对应的结果,我们求
m
a
x
max
max,就是这个序列最后剩下的长度,再用原序列长度减之即可
AC代码如下:
#include <bits/stdc++.h>
using namespace std;
const int N=1e5+10;
typedef long long ll;
int a[N],dp1[N],dp2[N],n;
int main(){
cin>>n;
for(int i=1;i<=n;i++) cin>>a[i];
for(int i=2;i<=n;i++)
for(int j=1;j<i;j++)
if(a[i]>a[j])
dp1[i]=max(dp1[i],dp1[j]+1);
for(int i=n-1;i>=1;i--)
for(int j=n;j>i;j--)
if(a[i]>a[j])
dp2[i]=max(dp2[i],dp2[j]+1);
int temp=0,res=0;
for(int i=1;i<=n;i++){
temp=dp1[i]+dp2[i]+1;
res=max(temp,res);
}
cout<<n-res<<endl;
return 0;
}
标签:dp2,dp1,合唱队,int,max,P1091,ti,序列,DP 来源: https://blog.csdn.net/qq_53287227/article/details/120164059