九度oj 题目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 这个题一开始用最简单的办法来做,果然超时了
代码如下#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:最长上升子序列的更多相关文章
- 九度OJ 题目1384:二维数组中的查找
/********************************* * 日期:2013-10-11 * 作者:SJF0115 * 题号: 九度OJ 题目1384:二维数组中的查找 * 来源:http ...
- hdu 1284 关于钱币兑换的一系列问题 九度oj 题目1408:吃豆机器人
钱币兑换问题 Time Limit: 2000/1000 MS (Java/Others) Memory Limit: 65536/32768 K (Java/Others) Total Sub ...
- 九度oj题目&吉大考研11年机试题全解
九度oj题目(吉大考研11年机试题全解) 吉大考研机试2011年题目: 题目一(jobdu1105:字符串的反码). http://ac.jobdu.com/problem.php?pid=11 ...
- 九度oj 题目1007:奥运排序问题
九度oj 题目1007:奥运排序问题 恢复 题目描述: 按要求,给国家进行排名. 输入: 有多组数据. 第一行给出国家数N,要求排名的国家数M,国家号 ...
- 九度oj 题目1087:约数的个数
题目链接:http://ac.jobdu.com/problem.php?pid=1087 题目描述: 输入n个整数,依次输出每个数的约数的个数 输入: 输入的第一行为N,即数组的个数(N<=1 ...
- 九度OJ题目1105:字符串的反码
tips:scanf,cin输入字符串遇到空格就停止,所以想输入一行字符并保留最后的"\0"还是用gets()函数比较好,九度OJ真操蛋,true?没有这个关键字,还是用1吧,还是 ...
- 九度oj题目1009:二叉搜索树
题目描述: 判断两序列是否为同一二叉搜索树序列 输入: 开始一个数n,(1<=n<=20) 表示有n个需要判断,n= 0 的时候输入结束. 接 ...
- 九度oj题目1002:Grading
//不是说C语言就是C++的子集么,为毛printf在九度OJ上不能通过编译,abs还不支持参数为整型的abs()重载 //C++比较正确的做法是#include<cmath.h>,cou ...
- 九度OJ题目1003:A+B
while(cin>>str1>>str2)就行了,多简单,不得不吐槽,九度的OJ真奇葩 题目描述: 给定两个整数A和B,其表示形式是:从个位开始,每三位数用逗号", ...
随机推荐
- tar打包压缩命令
1. tar命令 用法: tar [选项...] [FILE]... GNU ‘tar’将许多文件一起保存至一个单独的磁带或磁盘归档,并能从归档中单独还原所需文件. 示例 tar -cf archiv ...
- Objective-C Data Encapsulation
All Objective-C programs are composed of the following two fundamental elements: Program statements ...
- 快速排序的一种Java实现
快速排序是笔试和面试中很常见的一个考点.快速排序是冒泡排序的升级版,时间复杂度比冒泡排序要小得多.除此之外,快速排序是不稳定的,冒泡排序是稳定的. 1.原理 (1)在数据集之中,选择一个元素作为&qu ...
- C++拾遗(三)——函数
函数的定义 C++是一种静态强类型语言,对于每一次的函数调用,编译时都会检查其实参,必须与形参类型相同,或可被转换为该类型. 参数传递 普通的非引用类型的参数通过复制对应的实参实现初始化.引用形参直接 ...
- C#调用CMD程序
最近写了两个小程序都要调用Windows自带的命令行程序,一个是调用Openfiles.exe查询正在编辑的共享文档,一个是调用DiskPart.exe查询硬盘状态.两种命令行程序调用有点不同,记录一 ...
- 转载:使用Auto Layout中的VFL(Visual format language)--代码实现自动布局
本文将通过简单的UI来说明如何用VFL来实现自动布局.在自动布局的时候避免不了使用代码来加以优化以及根据内容来实现不同的UI. 一:API介绍 NSLayoutConstraint API 1 2 3 ...
- HDU 6069 Counting Divisors(区间素数筛法)
题意:...就题面一句话 思路:比赛一看公式,就想到要用到约数个数定理 约数个数定理就是: 对于一个大于1正整数n可以分解质因数: 则n的正约数的个数就是 对于n^k其实就是每个因子的个数乘了一个K ...
- 2017四川省赛E题( Longest Increasing Subsequence)
提交地址: https://www.icpc-camp.org/contests/4rgOTH2MbOau7Z 题意: 给出一个整数数组,F[i]定义为以i结尾的最长上升子序列,然后问以此删除掉第i个 ...
- Shift-Invariant论文笔记
ICML 2019 Making Convolutional Networks Shift-Invariant Again ICML 2019 Making Convolutional Network ...
- 来自-小坦克:Fiddler教程
Fiddler 教程 阅读目录 Fiddler的基本介绍 Fiddler的工作原理 同类的其它工具 Fiddler如何捕获Firefox的会话 Fiddler如何捕获HTTPS会话 Fiddler的基 ...