uva 10534(最长上升子序列O(nlogn))

介绍了一种寻找数字序列中最长的升序后降序子序列的算法,通过使用额外数组和二分查找优化了时间复杂度至O(nlogn)。

题意:在一个数字序列中找到最长的一个子序列,从数字上升到下降的长度最长,而且上升长度和下降长度相等,输出这个长度。

题解:直接用普通的0(n^2)的方法会超时,上网找了用O(nlogn)的方法理解了一下,加了一个c[N]数组,存的是当前最长上升子序列,如果是O(N^2)的做法会是遍历一遍从0到i的值然后更新最长上升子序列的长度,但是有了c数组可以直接根据此时的最长上升子序列更新f[i]的值,二分查找使时间复杂度降到n*logn。


#include <stdio.h>
#include <string.h>
const int N = 10005;
int n, s[N], f1[N], f2[N], c[N], d[N];

int search(int i, int *a) {
	int left = 0, right = n + 1, mid = (left + right) / 2;
	while (left < right) {
		if (s[i] > a[mid])
			left = mid + 1;
		else
			right = mid;
		mid = (left + right) / 2;
	}
	return right;
}

int main() {
	while (scanf("%d", &n) != EOF) {
		for (int i = 0; i < n; i++)
			scanf("%d", &s[i]);
		for (int i = 0; i <= n; i++)
			c[i] = d[i] = 0x3f3f3f3f;
		f1[0] = f2[n - 1] = 1;
		c[0] = d[0] = -1;
		c[1] = s[0];
		d[1] = s[n - 1];
		for (int i = 1; i < n; i++) {
			int j = search(i, c);
			c[j] = s[i];
			f1[i] = j;
		}
		for (int i = n - 2; i >= 0; i--) {
			int j = search(i, d);
			d[j] = s[i];
			f2[i] = j;
		}
		int res = -1, temp;
		for (int i = 0; i < n; i++) {
			temp = f1[i] > f2[i] ? f2[i] : f1[i];
			res = res < temp ? temp : res;
		}
		printf("%d\n", 2 * res - 1);
	}
	return 0;
}

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值