联盟周赛F题 csgo

联盟周赛F题 csgo

题目链接

https://nanti.jisuanke.com/t/40855

解题思路

简化之后,这道题就是要求上升序列的最少数目,也就是最少上升子序列的划分数目,也就是求下降子序列的最大长度。
这题用dp来做的话会很险,dp的时间复杂度是 O ( n 2 ) O(n^2) O(n2),这题 n n n 达到了 e 4 e^4 e4,时间级就是 e 8 e^8 e8 很容易TLE。所以用另外一种方法做,时间复杂度是 n l o g ( n ) nlog(n) nlog(n)
源代码如下:

#include <iostream>
#include <algorithm>
#define NUM 10050
#define MIN -1
using namespace std;

int dp[NUM];
int a[NUM];

bool cmp(int a, int b) {
	return a > b;
}

void solve(int n) {
	fill(dp, dp + n, MIN);
	for (int i = 0; i < n; ++i) {
		int index = lower_bound(dp, dp + n, a[i], cmp) - dp;
		dp[index] = a[i];
	}
}

int main(int argc, char** argv) {
	int n;
	while (cin >> n) {
		for (int i = 0; i < n; ++i) {
			scanf("%d", a+i);
		}
		solve(n);
		int i;
		for (i = 0; i < n; ++i) {
			if (dp[i] == MIN) break;
		}
		printf("%d\n", i);
	}
	
	return 0;
}

这题问题的转换是依据dilworth 定理,具体实现:上升链的最少划分数=下降链的最大长度。

另外关于求最长上升子序列,推荐《挑战程序设计竞赛》这本书。最长下降子序列和最长上升子序列的方法几乎一样,理解了最长上升子序列,最长下降子序列也就OK了。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值