题目描述:

给定一个整型数组, 求这个数组的最长严格递增子序列的长度。 譬如序列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. 利用UnblockNeteaseMusic实现网易云破版权,并实现shell可快速访问

    注:本篇包含mac及windows下安装方式详细 mac安装 前提:安装有node环境,可参考 mac下安装nodejs 安装 下载git代码到本地 git clone https://github. ...

  2. HDU 5469 Antonidas (树形DP,暴力)

    题意: 给一棵n节点的树图,每个点都是一个小写字母,要求找到两个点(a,b),从a->b的路径上形成了一个字符串为s.给出s,问是否存在这样的点对. 思路: 考虑一个点,要么从该点出发,要么在该 ...

  3. Window10 开启传统启动界面

    Windows 10沿袭了Windows 8的快速启动,导致在启动过程中无法通过按F8进入启动选项,这样当系统遇到问题无法进入时根本无法通过进入安全模式等方式进行处理(当然通过其他一些工具还是能够引导 ...

  4. ubuntu 14.04 安装mysql,并配置远程连接和中文乱码

    1. 安装MySQL的jar root@computer-PowerEdge-T30:~# sudo apt-get install mysql-server mysql-client在本次安装中,根 ...

  5. 一个具体的例子学习Java volatile关键字

    相信大多数Java程序员都学习过volatile这个关键字的用法.百度百科上对volatile的定义: volatile是一个类型修饰符(type specifier),被设计用来修饰被不同线程访问和 ...

  6. FIBON高精度

    #include<stdio.h> #include<string.h> int u,n; ],b[],h[]; ],y[],z[]; int main() { char s( ...

  7. WPF中Canvas使用

    首先知道Canvas有Left.Right.Top和Bottom这四个属性,放入Canvas的元素通过这四个属性来决定它们在Canvas里面的位置. 比如: Xaml: <Canvas Hori ...

  8. python之数据类型补充

    1. capitalize (首字母大写) 例题: s = "alex wusir" s1 = s.capitalize() # 格式 print(s1) ''' 输出结果 Ale ...

  9. common-configuration的一些应用

    此程序依赖commons-configuration-1.6.jar和commons-lang-2.6.jar两个jar包. 需要先在工程的src目录下建立如下几个文件: config.propert ...

  10. 【线段树】uoj#228. 基础数据结构练习题

    get到了标记永久化 sylvia 是一个热爱学习的女孩子,今天她想要学习数据结构技巧. 在看了一些博客学了一些姿势后,她想要找一些数据结构题来练练手.于是她的好朋友九条可怜酱给她出了一道题. 给出一 ...