NYOJ 题目214 单调递增子序列(二) dp+二分
2016-05-04 22:00
281 查看
单调递增子序列(二)
时间限制:1000 ms | 内存限制:65535 KB难度:4
描述
给定一整型数列{a1,a2...,an}(0<n<=100000),找出单调递增最长子序列,并求出其长度。
如:1 9 10 5 11 2 13的最长单调递增子序列是1 9 10 11 13,长度为5。
输入有多组测试数据(<=7)
每组测试数据的第一行是一个整数n表示序列中共有n个整数,随后的下一行里有n个整数,表示数列中的所有元素.每个整形数中间用空格间隔开(0<n<=100000)。
数据以EOF结束 。
输入数据保证合法(全为int型整数)!输出对于每组测试数据输出整形数列的最长递增子序列的长度,每个输出占一行。样例输入
7 1 9 10 5 11 2 13 2 2 -1
样例输出
5 1
思路:求最长单调子序列,由于数据量较大,传统的dp方法时间复杂度O(n^2)肯定不可行,所以就用了二分的方法,时间复杂度达到O(nlogn)。
具体方法:加一个maxv[]数组,maxv[i]代表长度为i的单调递增子序列最大元素的最小值。遍历a[]数组,每次都根据a[i]的值二分查找a[i]合适的位置,然后更新maxv[i]数组。maxv[len]数组的长度就是最长上升子序列的长度。
代码如下:
#include<iostream>
#include<cstring>
#include<cstdio>
using namespace std;
int maxv[100005];
int a[100005];
int binarysearch(int x,int len){//寻找maxv[i]中刚好大于等于x的位置
int left,right,mid;
left=1;
right=len;
while(left<=right){
mid=left+(right-left)/2;
if(maxv[mid]==x){
return mid;
}
else if(maxv[mid]<x){
left=mid+1;
}
else {
right=mid-1;
}
}
return left;
}
int main(){
int n,i,j,len;
while(scanf("%d",&n)!=EOF){
for(i=1;i<=n;i++){
scanf("%d",&a[i]);
}
maxv[1]=a[1];
len=1;
for(i=2;i<=n;i++){
if(a[i]>maxv[len]){//如果刚好大于目前maxv[i]中最大的,直接插到最后面
maxv[++len]=a[i];
}
else{
int pos=binarysearch(a[i],len);//二分查找
maxv[pos]=a[i];//将a[i]插入合适的位置
}
}
cout<<len<<endl;
}
return 0;
}
相关文章推荐
- C++二分查找在搜索引擎多文档求交的应用分析
- C语言编程中实现二分查找的简单入门实例
- C#二分查找算法实例分析
- 二分查找算法在C/C++程序中的应用示例
- 在MySQL中实现二分查找的详细教程
- 详解Android应用中屏幕尺寸的获取及dp和px值的转换
- 基于Android中dp和px之间进行转换的实现代码
- Android中dip、dp、sp、pt和px的区别详解
- Java实现二分查找算法实例分析
- Python二分查找详解
- 简介二分查找算法与相关的Python实现示例
- LFC1.0.0 版本发布
- Android px、dp、sp之间相互转换
- HP data protector软件学习1--基本角色与基本工作流程
- HP data protector软件学习2--软件组成与界面介绍
- 漫谈递归:二分查找算法的递归实现
- android中像素单位dp、px、pt、sp的比较
- 二分查找
- Android对px和dip进行尺寸转换的方法
- [LeetCode] Find Minimum in Rotated Sorted Array