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;
}
上一篇:OpenJudge 2711 合唱队形


下一篇:题解 卷