洛谷-AT2827最长上升子序列(dp)

6 篇文章 0 订阅

题目链接

题意:

给定一长度为n的数列,请在不改变原数列顺序的前提下,从中随机的取出一定数量的整数,并使这些整数构成单调上升序列。 输出这类单调上升序列的最大长度。

数据范围:

1<=n<=1000001<=n<=100000

思路:

dp

代码:

正常求LIS的方法应该下面这种:

#include<bits/stdc++.h>
using namespace std;
#define int long long
#define IOS ios::sync_with_stdio(false);cin.tie(0);cout.tie(0);
const int N=1e6+7;
const int inf=0x3f3f3f3f;
int a[N],dp[N];
signed main()
{
    int n;
    cin>>n;
    for(int i=1;i<=n;i++)
    {
        cin>>a[i];
    }
    for(int i=1;i<=n;i++)
    {
        dp[i]=1;//将以a[i]结尾的最长上升子序列的长度设为1
        for(int j=1;j<i;j++)
        {
            if(a[i]>a[j])
                dp[i]=max(dp[i],dp[j]+1);//如果a[i]>a[j],说明a[j]可以加到以a[i]结尾的子序列后面
        }
    }
    cout<<*max_element(dp+1,dp+1+n)<<endl;//取最大值
    return 0;
}

但是这道题数据有点大,所以要用其他方法,具体看代码:

#include<bits/stdc++.h>
using namespace std;
#define int long long
#define IOS ios::sync_with_stdio(false);cin.tie(0);cout.tie(0);
const int N=1e6+7;
const int inf=0x3f3f3f3f;
int a[N],d[N];
signed main()
{
    int n;
    cin>>n;
    for(int i=1;i<=n;i++)
    {
        cin>>a[i];
    }
    int len=1;d[1]=a[1];
    for(int i=1;i<=n;i++)
    {
        if(a[i]>d[len])//如果a[i]大于目前最长上升子序列的最优结尾,那么长度加一,结尾替换
        {
        	len++;
        	d[len]=a[i];//这里的d[N]数组记录的是长度为len的上升子序列的最优结尾
        }
        else//如果新出现的a[i]小于目前最长上升子序列的最优结尾
        {
        	d[lower_bound(d+1,d+len+1,a[i])-d]=a[i];//二分查找将该结尾放到最优的位置,替换掉前面比他大的最优结尾,成为最优结尾
		}
    }
    cout<<len<<endl;
}

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值