题目地址:http://ac.jobdu.com/problem.php?pid=1533

题目描述:

给定一个整型数组, 求这个数组的最长严格递增子序列的长度。 譬如序列1 2 2 4 3 的最长严格递增子序列为1,2,4或1,2,3.他们的长度为3。

输入:

输入可能包含多个测试案例。
对于每个测试案例,输入的第一行为一个整数n(1<=n<=100000):代表将要输入的序列长度
输入的第二行包括n个整数,代表这个数组中的数字。整数均在int范围内。

输出:

对于每个测试案例,输出其最长严格递增子序列长度。

样例输入:
4
4 2 1 3
5
1 1 1 1 1
样例输出:
2
1

参考《编程之美》2.16

对于前面i个元素的任何一个递增子序列,如果这个子序列的最大的元素比array[i+1]小,那么就可以将array[i+1]加在这个子序列后面,构成一个新的子序列。

比如当i=4的时候,目标序列为:1,-1,2,-3,4,-5,6,-7最长递增序列为:(1, 2),(-1, 2)。那么,只要4>2,就可以把4直接增加到前面的子序列中形成一个新的递增子序列。

因此,我们希望找到前i个元素的一个递增子序列,使得这个递增子序列的最大元素比array[i+1]小,且长度尽量地大。这样将array[i+1]加在该递增子序列后,便可找到以array[i+1]为最大元素的最长递增子序列。

仍然假设在数组的前i个元素中,以array[i]为最大元素的最长递增子序列的长度为LIS[i]。

同时,假设:

长度为1的递增子序列最大元素的最小值为MaxV[1];

长度为2的递增子序列最大元素的最小值为MaxV[2];

……

长度为LIS[i]的递增子序列最大元素的最小值为MaxV[LIS[i]]。

具体算法实现如下:

#include <stdio.h>

#define MAX 100000
#define VMAX 100001
#define MIN (-2147483647 - 1) int BSearch (int MaxV[], int start, int end, int key){
int mid; while (start <= end){
mid = start + ((end - start) >> 1);
if (MaxV[mid] < key){
start = mid + 1;
}
else if (MaxV[mid] > key){
end = mid - 1;
}
else
return mid;
}
return start;
} int LIS (int data[], int n){
int MaxV[VMAX];
MaxV[1] = data[0];
MaxV[0] = MIN;
int LIS[MAX]; int nMaxLIS = 1;
int i, j;
for (i=0; i<n; ++i)
LIS[i] = 1;
for (i=1; i<n; ++i){
j = BSearch (MaxV, 0, nMaxLIS, data[i]) - 1;
LIS[i] = j + 1;
if (LIS[i] > nMaxLIS){
nMaxLIS = LIS[i];
MaxV[LIS[i]] = data[i];
}
else if (MaxV[j] < data[i] && data[i] < MaxV[j + 1]){
MaxV[j+1] = data[i];
}
}
return nMaxLIS;
} int main(void){
int data[MAX];
int n;
int i; while (scanf ("%d", &n) != EOF){
for (i=0; i<n; ++i){
scanf ("%d", &data[i]);
}
printf ("%d\n", LIS (data, n));
} return 0;
}

根据参考资料可以知道完全不需要LIS[i]数组去定位,直接用MaxV[i]的下标作为LIS的长度即可。

代码更改如下:

#include <stdio.h>

#define MAX 100000
#define VMAX 100001
#define MIN (-2147483647 - 1) int BSearch (int MaxV[], int start, int end, int key){
int mid; while (start <= end){
mid = start + ((end - start) >> 1);
if (MaxV[mid] < key){
start = mid + 1;
}
else if (MaxV[mid] > key){
end = mid - 1;
}
else
return mid;
}
return start;
} int LIS (int data[], int n){
int MaxV[VMAX];
MaxV[1] = data[0];
MaxV[0] = MIN; int nMaxLIS = 1;
int i, j;
for (i=1; i<n; ++i){
j = BSearch (MaxV, 0, nMaxLIS, data[i]);
if (j > nMaxLIS){
nMaxLIS = j;
MaxV[j] = data[i];
}
else if (MaxV[j-1] < data[i] && data[i] < MaxV[j]){
MaxV[j] = data[i];
}
}
return nMaxLIS;
} int main(void){
int data[MAX];
int n;
int i; while (scanf ("%d", &n) != EOF){
for (i=0; i<n; ++i){
scanf ("%d", &data[i]);
}
printf ("%d\n", LIS (data, n));
} return 0;
}

HDOJ上相似的题目:1025 -- Constructing Roads In JGShining's Kingdom

参考资料:http://www.ahathinking.com/archives/117.html

九度OJ 1533 最长上升子序列 -- 动态规划的更多相关文章

  1. 九度oj 1530 最长不重复子串

    原题链接:http://ac.jobdu.com/problem.php?pid=1530 字符串简单题,看似O(n^2)的复杂度10000的数据量会tle,其实最长不重复子串不超过26个嘛... 如 ...

  2. 九度OJ 1528 最长回文子串 -- Manacher算法

    题目地址:http://ac.jobdu.com/problem.php?pid=1528 题目描述: 回文串就是一个正读和反读都一样的字符串,比如"level"或者"n ...

  3. 九度OJ 1011:最大连续子序列 (DP)

    时间限制:1 秒 内存限制:32 兆 特殊判题:否 提交:5615 解决:2668 题目描述:     给定K个整数的序列{ N1, N2, ..., NK },其任意连续子序列可表示为{ Ni, N ...

  4. 九度OJ 1011 最长子串

    #include <iostream> #include <string> #include <sstream> #include <math.h> u ...

  5. 九度oj 1528 最长回文子串

    原题链接:http://ac.jobdu.com/problem.php?pid=1528 小白书上的做法,不过这个还要简单些... #include<algorithm> #includ ...

  6. 九度OJ 1451 不容易系列之一 -- 动态规划

    题目地址:http://ac.jobdu.com/problem.php?pid=1451 题目描述: 大家常常感慨,要做好一件事情真的不容易,确实,失败比成功容易多了! 做好“一件”事情尚且不易,若 ...

  7. 九度OJ 1500 出操队形 -- 动态规划(最长上升子序列)

    题目地址:http://ac.jobdu.com/problem.php?pid=1500 题目描述: 在读高中的时候,每天早上学校都要组织全校的师生进行跑步来锻炼身体,每当出操令吹响时,大家就开始往 ...

  8. 【九度OJ】题目1195:最长&最短文本 解题报告

    [九度OJ]题目1195:最长&最短文本 解题报告 标签(空格分隔): 九度OJ http://ac.jobdu.com/problem.php?pid=1195 题目描述: 输入多行字符串, ...

  9. 【九度OJ】题目1069:查找学生信息 解题报告

    [九度OJ]题目1069:查找学生信息 解题报告 标签(空格分隔): 九度OJ [LeetCode] http://ac.jobdu.com/problem.php?pid=1069 题目描述: 输入 ...

随机推荐

  1. 教你50招提升ASP.NET性能(六):为了生动的用户体验,总是在客户端验证

    (12)For a snappy user experience, always validate on the client 招数12: 为了生动的用户体验,总是在客户端验证 To avoid un ...

  2. powershell.exe直接运行命令

    powershell.exe -Command "& { ('time={0},user={1}' -f (get-date),(whoami)) | Out-File " ...

  3. Process学习

    主要系统总结下我对进程的认识,以前理解得不够全面不够深入.本文肯定还不够好,当有新的认识新的理解后还会随时来更新.读完本文,下面几个问题便可理解清楚. 1.进程是什么? 2.为什么要有进程这个概念? ...

  4. Android develop tricks——整理自国外的一些Blog

    ViewDragHelper --视图拖动是一个比較复杂的问题.这个类能够帮助解决不少问题.假设你须要一个样例,DrawerLayout就是利用它实现扫滑.Flavient Laurent 还写了一些 ...

  5. spring关于“transactionAttributes”的相关配置

    spring关于"transactionAttributes"的相关配置 <bean id="baseTransactionProxy" class=&q ...

  6. iOS开发——高级技术&生成二维码

      生成二维码 因为项目里需要新增个功能,该功能用到了二维码技术.于是我便查阅了资料,先学习了二维码的生成. 我们使用libqrencode库来生成二维码.下载地址http://download.cs ...

  7. There is no Action mapped for action name XXX. - [unknown location]

    今天被这个问题费了不少时间,原因是缺少了 struts2-json-plugin-2.3.1.2.jar 包 当然,有时候也可能是缺少其他包, 把这个包添加到lib文件夹后还要刷新,clean一下,因 ...

  8. linux 学习笔记 Linux内核的四大功能简介

    一 内存管理 默认情况下,运行在Linux系统上的每个进程都有各自的内存页面:进程不能访问其他进程正在使用的内存页面. 内核维护着自己的内存区域 用户进程不能访问内核进程的内存 可以创建一些共享内存页 ...

  9. Android(java)学习笔记136:Java类初始化顺序

    Java类中初试化的顺序: 由此得出Java普通类初始化顺序结论: 静态变量 静态初始化块 变量 初始化块 构造器 由此得出Java继承类初始化顺序结论:     1 .继承体系的所有静态成员初始化( ...

  10. AppUse学习笔记

    AppUse学习笔记http://www.docin.com/p-786350740.html