最长上升子序列

#include <iostream>
#include <algorithm>
using std::cin;
using std::cout;
using std::endl;
using std::max;
constexpr int N=105;
int a[N],f[N];
int main(int argc,char* args[]){
	std::ios::sync_with_stdio(false);
	cin.tie(nullptr);cout.tie(nullptr);
	int n;
	cin>>n;
	for(int i=0;i<n;++i){
		cin>>a[i];
	}
	for(int i=0;i<n;++i){
		f[i]=1;
	}
	int len=1;
	for(int i=1;i<n;++i){
		for(int j=0;j<i;++j){
			if(a[j]<a[i])
				f[i]=max(f[i],f[j]+1);
		}
		len=max(len,f[i]);
	}
	cout<<len<<endl;
	return 0;
}
这段代码是一个用于求解最长不下降子序列长度的问题。

代码首先定义了一个常量N,并声明了两个整型数组a和f,分别用于存储输入序列和子序列的长度。数组a的大小为N,表示输入序列的最大长度。

接下来,主函数main中,首先读入一个整数n,表示输入序列的长度。然后通过一个循环,依次读入n个整数,存储到数组a中。

随后,通过一个循环,初始化数组f的初始值为1,表示每个元素自身构成长度为1的子序列。

然后,定义一个变量len,用来记录不下降子序列的最大长度,初始值为1。

再通过一个循环,从第二个元素开始遍历数组a。对于每个元素a[i],遍历从0到i-1的元素a[j],如果a[j]小于a[i],则可以将a[i]添加到以a[j]为结尾的子序列后面,从而得到一个更长的不下降子序列,此时将f[i]更新为f[j]+1。

最后,每次更新f[i]之后,通过比较f[i]和len的大小,更新len为当前最大的子序列长度。

最终,输出得到的最大不下降子序列长度len。

这段代码的时间复杂度为O(n^2),其中n为输入序列的长度。

#include <iostream>
#define len (*b)
using std::cin;
using std::cout;
using std::endl;
constexpr int N=105;
int b[N+1]={1};
int find(int x){
	int l=1,r=len;
	while(l<r){
		int mid=l+r>>1;
		if(b[mid]>=x){
			r=mid;
		}else{
			l=mid+1;
		}
	}
	return l;
}
int main(int argc,char const* args[] ){
	int n,val;
	std::ios::sync_with_stdio(false);
	cin.tie(nullptr);cout.tie(nullptr);
	cin>>n;
	cin>>b[1];
	for(int i=2;i<=n;++i){
		cin>>val;
		b[val>b[len]?++len:find(val)]=val;
	}
	cout<<len<<endl;
	return 0;
}

代码首先定义了一个宏`len`,表示不下降子序列的长度。接着定义了一个数组`b`,用于存储不下降子序列,数组的大小是N+1。初始时,令`b[0]`为1,表示不下降子序列的长度为1。

接下来,代码定义了一个函数`find`,用于在数组`b`中查找第一个大于等于目标值`x`的位置。这里使用了二分查找的思想。

主函数`main`中,首先读入一个整数`n`,表示序列的长度。接着读入第一个元素,并将其存储到数组`b`的第一个位置。

然后从第二个元素开始遍历剩下的元素。在每一次遍历中,读入一个元素`val`,并根据该元素的大小更新数组`b`中的值。如果`val`大于数组`b`中的最后一个元素,说明可以将`val`添加到不下降子序列中,并将`len`加1。反之,通过调用函数`find`找到`val`在数组`b`中的位置,并更新该位置的值为`val`。

最终,函数返回0,表示程序执行结束。

这段代码的时间复杂度为O(nlogn),其中n为序列的长度。

  • 8
    点赞
  • 6
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

朝闻道 晨星

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值