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

来源:互联网 发布:airbnb 代订陷阱 淘宝 编辑:程序博客网 时间:2024/05/21 15:40

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

题解:直接用普通的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;elseright = 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;}

0 0
原创粉丝点击