单调递增子序列(二)(nyoj214)
2016-04-11 23:55
169 查看
单调递增子序列(二)
时间限制: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
常规解法:动态规划
见单调递增最长子序列
#include <stdio.h>
#include <string.h>
int s[100005]={0};
int dp[100005]={0};
int main()
{
int n;
while(~scanf("%d", &n)&&n!=EOF)
{
int max=0;
for(int i=0; i<n; i++)
{
scanf("%d", &s[i]);
dp[i] = 0;
for(int j=0; j<i; j++)
if(s[j]<s[i] && dp[i]<dp[j]) dp[i]=dp[j];
dp[i]++;
if(max<dp[i]) max=dp[i];
}
printf("%d\n", max);
}
return 0;
}
虽然动归的效率不错,但是数据量达到10w级,而时间又限制在1s以内,单纯动归的效率还是不够。
动归+二分查找:
#include<math.h>
#include<stdio.h>
#include<stdlib.h>
#include<string.h>
int dp[100010];
int binarysearch(int key,int len)
{
int left=0,right=len-1,mid;
while(left<=right)
{
mid=(left+right)/2;
if(key==dp[mid])
return mid;
else if(key>dp[mid])
left=mid+1;
else
right=mid-1;
}
return left;
}
int main()
{
int n,i,j,k,len;
while(scanf("%d",&n)!=EOF)
{
scanf("%d",&k);
dp[0]=k;
len=1;
for(i=1; i<n; i++)
{
scanf("%d",&k);
j=binarysearch(k,len);
dp[j]=k;
len=j+1>len?j+1:len;
//for(int x=0; x<len; x++)
// printf("%d ", dp[x]);
//printf("\n");
}
printf("%d\n",len);
}
return 0;
}
//测试数据:
//7
//1 9 10 5 11 2 13
//12
//1 9 10 5 11 2 13 3 4 5 6 7
//2
//2 -1
相关文章推荐
- C++动态规划之最长公子序列实例
- C++动态规划之背包问题解决方法
- C#使用动态规划解决0-1背包问题实例分析
- 动态规划
- C++ 动态规划
- DP(动态规划) 解游轮费用问题
- 动态规划的用法——01背包问题
- 动态规划的用法——01背包问题
- 《收集苹果》 动态规划入门
- 《DNA比对》蓝桥杯复赛试题
- 《背包问题》 动态规划
- 自顶向下动态规划解决最长公共子序列(LCS)问题
- 初学ACM - 半数集(Half Set)问题 NOJ 1010 / FOJ 1207
- 关于爬楼梯的动态规划算法
- 动态规划 --- hdu 1003 **
- DP问题各种模型的状态转移方程
- 0-1背包解题过程
- 背包问题
- USACO 3.2.2:Stringsobits
- 字符串编辑距离