牛客网-合唱队形【dp-最大子序列变形】

在这里插入图片描述
删除最少的人组成这种合唱队形,该问题可以化简为:满足该队形性质的最长序列,只要找到了该最长序列,用总人数减去序列长度就得到了最少删除的人数。

那么如何找这个序列呢?其实我们可以把他看成两部分,左侧是一个最长子序列问题,右侧也是一个最长子序列问题,他们在Ti处汇总。因此我们从左向右求一个最长递增子序列,从右向左再求一个最长递增子序列,然后得到两个dp数组,dp1,dp2,在遍历每一个汇点i:dp1[i]+dp2[i]-1就是以i点为中心所能形成的合唱队形的最大长度。

int main() {
	int n; ll a[MAX], dp1[MAX], dp2[MAX];//dp1:正向最长递增子序列 dp2:反向最长递增子序列
	while (cin >> n) {
		for (int i = 1; i <= n; i++)cin >> a[i];
		fill(dp1, dp1 + MAX, 1);
		fill(dp2, dp2 + MAX, 1);
		for (int i = 1; i <= n; i++)
			for (int j = 1; j < i; j++)
				if (a[j]<a[i] && dp1[j] + 1>dp1[i]) dp1[i] = dp1[j] + 1;
		for (int i = n; i >= 0; i--) 
			for (int j = n; j > i; j--)
				if (a[i] > a[j] && dp2[j] + 1 > dp2[i])dp2[i] = dp2[j] + 1;
		ll res = 0;
		for (int i = 1; i <= n; i++) 
			if (dp1[i] + dp2[i] - 1 > res)res = dp1[i] + dp2[i] - 1;
		
		cout << n - res << endl;
	}
}
发布了269 篇原创文章 · 获赞 16 · 访问量 1万+

猜你喜欢

转载自blog.csdn.net/csyifanZhang/article/details/105693633
今日推荐