C - Emojis Gym - 102566C题解

题目地址
题目大意:给出一个序列,求一个最长不下降序列使得夹在这个序列中间的数最少。
例如序列3 5 2 7 4 11 10
可以找到两个4长的不下降序列3 5 7 11和3 5 7 10,显然前者夹在这个序列中间的数更少,为2.
题目分析:由于题目中N达到1e5,所以求最长不下降子序列要使用nlogn的方法,比较常用的就是贪心加二分法,这个题实际是考对这种方法的理解。
我们在使用upper_bound进行求解的时候,用一个pos数组记录一下每个元素在dp数组中的放置记录,有了pos数组的帮助就可以方便求出使得夹在序列中的数最少的序列。序列长度固定,有了起点和终点即可求得需要去掉的数的个数,所以要使起点和终点尽可能接近。一开始我想的是找到最靠前的可以做序列最后一个元素的位置,然后从这个位置向前递推只到推到起点。结果在第18个点WA了,后来想了想发现终点未必一定在最靠前的位置取得,比如假设最长长度为4,pos数组为1223341234,那么应该选择后面的那个4。所以要枚举终点然后找到离终点最近的起点。
代码

#include <bits/stdc++.h>
using namespace std;
const int MAX_N = 1e5 + 5;
const int INF = 10000000000;
int T, n, cnt, ans, a[MAX_N], dp[MAX_N], pos[MAX_N];
int main() {
	cin >> T;
	while (T--) {
		cnt = 0; ans = INF;
		scanf("%d", &n);
		fill(dp, dp + n + 1, INF);
		for (int i = 1; i <= n; i++) scanf("%d", &a[i]);
		for (int i = 1; i <= n; i++) { 
			int tmp = upper_bound(dp + 1, dp + n + 1, a[i]) - dp;
			dp[tmp] = a[i];
			pos[i] = tmp;
		}
		cnt = lower_bound(dp + 1, dp + n + 1, INF) - dp - 1;
		for (int i = n; i; i--) {
			int j, k;
			if (pos[i] == cnt) {
				j = i - 1, k = cnt - 1;
				while (k) {
					if (pos[j] == k) k--;
					j--;
				}
				ans = min(ans, i - j - cnt);
			}
		}
		printf("%d %d\n", cnt, ans);
	}
	return 0;
}
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值