题目描述:

给定一个整型数组, 求这个数组的最长严格递增子序列的长度。 譬如序列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 这个题一开始用最简单的办法来做,果然超时了
代码如下
 #include <cstdio>
int toDo[];
int cnt[]; int n;
int main(int argc, char const *argv[])
{
while(scanf("%d",&n) != EOF) {
for(int i = ; i < n ; i++) {
scanf("%d",&toDo[i]);
}
int max = ;
for(int i = ; i < n; i++) {
int maxi = ;
for(int j = i-; j >= ; j--) {
if(toDo[j] < toDo[i] && maxi < cnt[j]) {
maxi = cnt[j];
}
}
cnt[i] = maxi + ;
if(max < cnt[i]) {
max = cnt[i];
}
}
printf("%d\n",max);
}
return ;
}

后来参考了许多别人的博客,才明白应该这样做

首先,你需要一个数组minNum[i]来记录达到长度i的最小数字是几,这个数组必然是递增的,因为长度更长的它的数字肯定更大。

那么,当一个新数字来的时候,假设现在最长的长度为k

如果它比minNum[k]大,那么minNum[++k] = newNum;

如果不比minNum[k]大,则需要去更新这个数组中的元素。具体需采用二分法来找到这个数字的位置,接着更新之。

但一开始提交错误,原来的代码是这样的

 #include <cstdio>
int toDo[];
int minNum[]; int n; int bSearch(int p,int low, int high) {
if(low < high) {
int mid = (low + high)/;
if(minNum[mid] == p) {
return mid;
}
else if(minNum[mid] < p) {
return bSearch(p, mid+, high);
}
else {
return bSearch(p, low, mid-);
}
}
return low;
} int main(int argc, char const *argv[])
{
while(scanf("%d",&n) != EOF) {
for(int i = ; i < n ; i++) {
scanf("%d",&toDo[i]);
} minNum[] = toDo[];
int k = ;
for(int i = ; i < n; i++) {
if(toDo[i] > minNum[k]) {
minNum[++k] = toDo[i];
}
else {
int p = bSearch(toDo[i], , k);
minNum[p] = toDo[i];
}
}
printf("%d\n",k);
}
return ;
}

经过实验,发现测试数据为 4 5 6 1 2 3 5就会出错,

检查之后发现是二分搜索的错误,当minNum为 1 5 6时, 2 的到来使它变为2 5 6, 而不是1 2 6

修改在17行

代码如下

 #include <cstdio>
int toDo[];
int minNum[]; int n; int bSearch(int p,int low, int high) {
if(low < high) {
int mid = (low + high)/;
if(minNum[mid] == p) {
return mid;
}
else if(minNum[mid] < p) {
return bSearch(p, mid+, high);
}
else {
return bSearch(p, low, mid);
}
}
return low;
} int main(int argc, char const *argv[])
{
while(scanf("%d",&n) != EOF) {
for(int i = ; i < n ; i++) {
scanf("%d",&toDo[i]);
} minNum[] = toDo[];
int k = ;
for(int i = ; i < n; i++) {
if(toDo[i] > minNum[k]) {
minNum[++k] = toDo[i];
}
else {
int p = bSearch(toDo[i], , k);
minNum[p] = toDo[i];
}
}
printf("%d\n",k);
}
return ;
}

事实上,不需要toDo这个数组,代码如下

 #include <cstdio>
int toDo;
int minNum[];
int n; int bSearch(int p,int low, int high) {
if(low < high) {
int mid = (low + high)/;
if(minNum[mid] == p) {
return mid;
}
else if(minNum[mid] < p) {
return bSearch(p, mid+, high);
}
else {
return bSearch(p, low, mid);
}
}
return low;
} int main(int argc, char const *argv[])
{
while(scanf("%d",&n) != EOF) {
int k = ;
for(int i = ; i < n ; i++) {
scanf("%d",&toDo);
if(k == ) {
minNum[++k] = toDo;
continue;
}
if(toDo > minNum[k]) {
minNum[++k] = toDo;
}
else {
int p = bSearch(toDo, , k);
minNum[p] = toDo;
}
}
printf("%d\n",k);
}
return ;
}

今天看书,知道有个函数是lower_band(), upper_band(),fill();

需要#include <algorithm>

using namespace std

lower_band()从已排好序的序列a中利用二分搜索(区间左开右闭)找出指向满足ai>=k的ai的最小指针

lower_band(a, a+n, k)

可以写出如下代码

 #include <cstdio>
#include <algorithm>
using namespace std;
int toDo;
int dp[];
int n; int main(int argc, char const *argv[])
{
while(scanf("%d",&n) != EOF) {
int k = ;
for(int i = ; i < n ; i++) {
scanf("%d",&toDo);
if(k == ) {
dp[k++] = toDo;
}
else {
int *p = lower_bound(dp,dp+k,toDo);
if(p - dp == k) {
dp[k++] = toDo;
}
else {
*p = toDo;
}
} } printf("%d\n",k);
}
return ;
}

甚至是

 #include <cstdio>
#include <algorithm>
#define inf 2147483647
using namespace std;
int toDo;
int dp[];
int n; int main(int argc, char const *argv[])
{
while(scanf("%d",&n) != EOF) {
int k = ;
fill(dp, dp+n,inf);
for(int i = ; i < n ; i++) {
scanf("%d",&toDo);
*lower_bound(dp,dp+n,toDo) = toDo;
} printf("%d\n",lower_bound(dp, dp+n, inf) - dp);
}
return ;
}

九度oj 题目1533:最长上升子序列的更多相关文章

  1. 九度OJ 题目1384:二维数组中的查找

    /********************************* * 日期:2013-10-11 * 作者:SJF0115 * 题号: 九度OJ 题目1384:二维数组中的查找 * 来源:http ...

  2. hdu 1284 关于钱币兑换的一系列问题 九度oj 题目1408:吃豆机器人

    钱币兑换问题 Time Limit: 2000/1000 MS (Java/Others)    Memory Limit: 65536/32768 K (Java/Others) Total Sub ...

  3. 九度oj题目&amp;吉大考研11年机试题全解

    九度oj题目(吉大考研11年机试题全解) 吉大考研机试2011年题目: 题目一(jobdu1105:字符串的反码).    http://ac.jobdu.com/problem.php?pid=11 ...

  4. 九度oj 题目1007:奥运排序问题

    九度oj 题目1007:奥运排序问题   恢复 题目描述: 按要求,给国家进行排名. 输入:                        有多组数据. 第一行给出国家数N,要求排名的国家数M,国家号 ...

  5. 九度oj 题目1087:约数的个数

    题目链接:http://ac.jobdu.com/problem.php?pid=1087 题目描述: 输入n个整数,依次输出每个数的约数的个数 输入: 输入的第一行为N,即数组的个数(N<=1 ...

  6. 九度OJ题目1105:字符串的反码

    tips:scanf,cin输入字符串遇到空格就停止,所以想输入一行字符并保留最后的"\0"还是用gets()函数比较好,九度OJ真操蛋,true?没有这个关键字,还是用1吧,还是 ...

  7. 九度oj题目1009:二叉搜索树

    题目描述: 判断两序列是否为同一二叉搜索树序列 输入:                        开始一个数n,(1<=n<=20) 表示有n个需要判断,n= 0 的时候输入结束. 接 ...

  8. 九度oj题目1002:Grading

    //不是说C语言就是C++的子集么,为毛printf在九度OJ上不能通过编译,abs还不支持参数为整型的abs()重载 //C++比较正确的做法是#include<cmath.h>,cou ...

  9. 九度OJ题目1003:A+B

    while(cin>>str1>>str2)就行了,多简单,不得不吐槽,九度的OJ真奇葩 题目描述: 给定两个整数A和B,其表示形式是:从个位开始,每三位数用逗号", ...

随机推荐

  1. hdoj薛猫猫杯程序设计网络赛1003 球球大作战

    思路: 二分,check函数不是很好写. 实现: 1. #include <bits/stdc++.h> using namespace std; typedef long long ll ...

  2. jsonwebapi请求头的设置

    Content-Type: application/x-www-form-urlencoded; charset=UTF-8

  3. SIT&UAT

  4. Python实现扫描作业配置自动化

    持续集成平台接入扫描作业是一项繁琐而又需要细致的工作,于是趁着闲暇时间,将代码扫描作业用Python代码实现了配置自动化. 每次配置作业的过程中,都会在checkcode1或者checkcode3上 ...

  5. python 基础网络编程2

    python 基础网络编程2 前一篇讲了socketserver.py中BaseServer类, 下面介绍下TCPServer和UDPServer class TCPServer(BaseServer ...

  6. App Store中的开源游戏汇总

    这是国外达人收集的曾经在app store上出现过,或者还在app store上卖的iOS开源游戏的列表,其中代码大部分人你托管在google code或者github上,其中有很多使用Cocos2D ...

  7. Resize a UIImage the right way

    When deadlines loom, even skilled and experienced programmers can get a little sloppy. The pressure ...

  8. Scroller 界面滑动

    Scroller 滑动之后滑动器子标签里面的控件,其自身是不动的.这里点在下面的进阶会体现出来.  1. 继承LinearLayout, 相对布局也可以. public class MyLinearL ...

  9. MIPS程序设计实例

    第一题:用系统功能调用实现简单输入输出 题目要求 利用系统功能调用从键盘输入,转换后在屏幕上显示,具体要求如下: 1.如果输入的是字母(A~Z,区分大小写)或数字(0~9),则将其转换成对应的英文单词 ...

  10. WPF中给Button加上图标和文字

    要实现在Button里面加入图标或者图形以及文字,我们就需要在Button里面用一个WrapPanel控件,这个WrapPanel控件会把我们的图标或者文字进行包裹,并显示出来. Xaml: < ...