九度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,其表示形式是:从个位开始,每三位数用逗号", ...
随机推荐
- IO多路复用机制(转)
1.简介 希望通过这篇文章,可以回答以下几个问题? 为什么需要IO多路复用? 什么是IO多路复用机制? IO多路复用的机制该怎么使用? epoll比select/poll相比,优势在哪里? 在了解I/ ...
- CF1060D Social Circles
思路: 贪心.既然每个人的左边是其他人的右边,每个人的右边是其他人的左边,那么使重叠的部分最多即可. 实现: #include <bits/stdc++.h> using namespac ...
- BZOJ3073: [Pa2011]Journeys(线段树优化建图 Dijkstra)
题意 \(n\)个点的无向图,构造\(m\)次边,求\(p\)到任意点的最短路. 每次给出\(a, b, c, d\) 对于任意\((x_{a \leqslant x \leqslant b}, y_ ...
- 【学习笔记】六:面向对象的程序设计——理解JS中的对象属性、创建对象、JS中的继承
ES中没有类的概念,这也使其对象和其他语言中的对象有所不同,ES中定义对象为:“无序属性的集合,其属性包含基本值.对象或者函数”.现在常用的创建单个对象的方法为对象字面量形式.在常见多个对象时,使用工 ...
- C# 一维数组 冒泡排序
假设有个三个杯子 一个杯子中有一个紫色的乒乓球 一个没有 一个有红色乒乓球 杯子不能动 怎么把紫色和红色的调换呢 主要是先把紫色的放到空的杯子 在把红的放到紫色原来的杯子 再把 ...
- vue+element ui项目总结点(三)富文本编辑器 vue-wangeditor
1.参考 https://www.npmjs.com/package/vue-wangeditor 使用该富文本编辑器 <template> <div class="egi ...
- ipsec配置strongswan.conf和ipsec.conf
配置strongswan.conf vi /usr/local/etc/strongswan.conf # strongswan.conf - strongSwan configuration fil ...
- leetcode_1049. Last Stone Weight II_[DP]
1049. Last Stone Weight II https://leetcode.com/problems/last-stone-weight-ii/ 题意:从一堆石头里任选两个石头s1,s2, ...
- 什么是闭包(Closure)?
http://kb.cnblogs.com/page/111780/ 这个问题是在最近一次英格兰Brighton ALT.NET Beers活动中提出来的.我发现,如果不用代码来演示,你很难单用话语把 ...
- CentOS 6.7安装(一)
CentOS 6.7安装 1.将光盘放入服务器,选择从光盘启动,选择“Install or upgrade an existing system”,并跳过光盘测试. 2.选择安装过程中使用的语言,默认 ...