基准时间限制:1 秒 空间限制:131072 KB 分值: 0 难度:基础题
收藏
关注
给出长度为N的数组,找出这个数组的最长递增子序列。(递增子序列是指,子序列的元素是递增的)
例如:5 1 6 8 2 4 5 10,最长递增子序列是1 2 4 5 10。
Input
第1行:1个数N,N为序列的长度(2 <= N <= 50000) 第2 - N + 1行:每行1个数,对应序列的元素(-10^9 <= S[i] <= 10^9)
Output
输出最长递增子序列的长度。
Input示例
8 5 1 6 8 2 4 5 10
Output示例
5 常规的解法是设dp[i]表示前i位的最长上升序列长度,然后每次更新dp[i+1]都要与[0,i]进行一次比较。时间复杂度为O(n^2),完美超时。 想想怎么去优化呢?看看更新dp[i+1]需要比较这么多次吗?假设dp[i+1]=len,那么我们只要与值为len-1的去进行比较,所以不妨设b[i]表示最长上升序列为i的dp数组中的最小值。
1 /*用数组b来存放最长上升序列,然后枚举数组a中元素看能否插入b数组。 2 那么b数组的大小即为所求。 3 */ 4 #include <iostream> 5 #include <algorithm> 6 #include <cstring> 7 using namespace std; 8 typedef long long ll; 9 ll b[50005]; 10 ll a[50005]; 11 ll n; 12 void solve() 13 { 14 memset(b,0,sizeof(b)); 15 b[0]=a[0]; 16 int sum=1; 17 for(int i=1;i<n;i++)//枚举a数组 18 { 19 int pos=lower_bound(b,b+sum,a[i])-b;//lower_bound()返回值为b数组中有几个比a[i]小的 20 b[pos]=a[i]; //或者理解为用a[i]去更新b序列应更新的位置 21 sum=max(sum,pos+1);//长度更新 22 } 23 cout<<sum<<endl; 24 } 25 int main() 26 { 27 cin>>n; 28 for(int i=0;i<n;i++) 29 cin>>a[i]; 30 solve(); 31 return 0; 32 }
代码才是最清晰的语言
时间: 2024-10-19 10:58:48