题目地址: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. 如何在线缩小jpg图片的大小

    直接使用在线PS保存成更小格式,即可! 在线PS网址:http://www.webps.cn/ 打开图片 点击保存 直接拖动滑动条就可以改变图片大小

  2. Aizu 2450 Do use segment tree 树链剖分+线段树

    Do use segment tree Time Limit: 1 Sec Memory Limit: 256 MB 题目连接 http://www.bnuoj.com/v3/problem_show ...

  3. JS知识点备忘

    做前端久了,会发现很多比较杂的知识点,平时很少用到(往往在面试的时候经常见到),但是遇到的时候会很揪心...所以遇到的时候把它记录下来,但求有个印象,再次遇到时,可以在这里快速找到解决. 1.文档碎片 ...

  4. [Bootstrap] 4. Typogrphy

    What is Typography When we talk about typography, it's a big subject! Which of the following fall un ...

  5. iOS 音频拼接

    工作中或许会遇到这样的需求,将两段不同的音频合成一个音频(暂且称之为音频拼接),实现起来相对来说不是很难,再介绍如何拼接之前,先了解下AVFoundation下的几个基本知识点. 基本知识 AVAss ...

  6. Mysql字符集设置 2 图

    基本概念 • 字符(Character)是指人类语言中最小的表义符号.例如'A'.'B'等: • 给定一系列字符,对每个字符赋予一个数值,用数值来代表对应的字符,这一数值就是字符的编码(Encodin ...

  7. Listview实现分页下载

    分析: * 1.初始控件,展示第一页数据 * 2.设置触发条件 * 1.设置滚动监听 * 2.判断是否在底部 * 3.判断是否停止滚动 * 4.更改网络请求参数为下一页 * 5.异步网络请求 * 6. ...

  8. 大陆居民身份证验证方法(java)

    1.设置接口 @Constraint(validatedBy = ChineseIdNumberValidator.class) @Target({ElementType.METHOD, Elemen ...

  9. Python中作用域的特别之处

    def a(): a = [] def aappend(): a.append(1) aappend() print a def b(): b = 1 def bchange(): b += 1 # ...

  10. 关于JFace带复选框的树

    树的复选框用CheckboxTreeViewer实现.由于其子类ContainerCheckedTreeViewer在没有选择全部子节点时可以自动将父节点设置成灰选,所以实现树的复选框更多的是用Con ...