动态规划-求LIS和时间优化

(一)O(n^2)算法

相信你已经掌握了。

【Code】严格的最长递增子序列

	for(int i=1; i<=N; i++) {
		f[i] = 1;
		for(int j=1; j<i; j++)
			if(a[j] < a[i] && f[i] < f[j] + 1) f[i] = f[j] + 1;
		ans = max(ans, f[i]);
	}


(二)O(n logn)算法

用数组d,d[i]表示LIS为i的这个子序列末尾是谁(有多个取最小值)

当前LIS长度为len,如果A[i] > D[len] 就加到这个LIS末尾,len++

否则用二分查找找到一个刚好满足的D[k]。

思考二分查找的正确性:D数组一定是递增的。D的下标是LIS的长度,因此长度为1的LIS结尾一定不大于长度为2的LIS结尾.

【Code】不严格LIS

#include <iostream>
using namespace std;

#define DEBUG 0 //可以打印D数组帮助思考 

int Search(int *a, int n, int w) {
	int l = 1, r = n, ans = -1, mid;
	while(l <= r) {
		mid = l + r >> 1;
		if(a[mid] <= w) l = (ans = mid) + 1;
		else r = mid - 1;
	}
	return ans;
}

int a[100010], d[100010];
int N, len;

int main() {
	scanf("%d", &N);
	for(int i=1; i<=N; i++) scanf("%d", &a[i]);
	len = 1;
	d[1] = a[1];
	for(int i=2; i<=N; i++) {
		if(a[i] >= d[len]) d[++len] = a[i];
		else {
			int pos = Search(d, N, a[i]);
			d[pos] = a[i];
		}
	}
	if(DEBUG) for(int i=1; i<=len; i++) cout << d[i] << ' ';
	cout << len << endl; 
	return 0;
}

仔细想想,好像并不是DP,只是一个二分。(Orz)

猜你喜欢

转载自blog.csdn.net/Binary_Heap/article/details/79196303
今日推荐