最长上升子序列加强版(树状数组优化)

题目

Description

给出N个数,它们各不相同,求最长上升子序列 

Input

先给出一个数字N,代表有N组数据
对于每组数据,先给出一个数字TOT,TOT小于等于40000.
接下来有TOT个数字,为1到40000的某个排列.

Output

针对每组数据,输出最长上升序列的长度

Sample Input

4
6
4 2 6 3 1 5
10
2 3 4 5 6 7 8 9 10 1
8
8 7 6 5 4 3 2 1 9 5 8 9 2 3 1 7 4 6

Sample Output

3
9
1
4

思路:

本是一道dp题,但数据给了加强,那么就需要优化;

首先来看看dp的代码:

    dp[1]=1;
    for(ll i=1;i<=n;i++)
    {
        ll sum=0;
        for(ll j=1;j<=i;j++)
        if(a[j]<a[i])
            sum=max(sum,dp[j]);
        dp[i]=sum+1;
    }
    ll ans=0;
    for(ll i=1;i<=n;i++)
        ans=max(ans,dp[i]);
    printf("%lld\n",ans);

那么怎么优化呢?-----树状数组

我们看到代码中有两行 

for(ll j=1;j<=i;j++)
        if(a[j]<a[i])

一般有这个代码的dp题目都可以用树状数组来优化;

如果不信的巨佬看看我之前写的树状数组优化题目;

所以

for(ll j=1;j<=i;j++)
if(a[j]<a[i])
    sum=max(sum,dp[j]);

就可以转化为求1-a[i]的最大值

如下网址:https://www.cnblogs.com/wzx-RS-STHN/p/13193271.html(树状数组中求1-x的最大值);

 

代码

#include<bits/stdc++.h>
typedef long long ll;
using namespace std;
inline ll read()
{
    ll a=0,f=1; char c=getchar();
    while (c<'0'||c>'9') {if (c=='-') f=-1; c=getchar();}
    while (c>='0'&&c<='9') {a=a*10+c-'0'; c=getchar();}
    return a*f;
}
ll n,mx;
ll sum[40001],a[40001];
inline ll lowbit(ll x)
{
    return x&(-x);
}
inline void insert(ll x,ll y)//加入 
{
    while(x<=mx)//!!! 
    {
        sum[x]=max(sum[x],y);//cout<<"a"<<x<<" "<<y<<endl;改代码的痕迹 
        x+=lowbit(x);
    }
}
inline ll findout(ll x)//查找 
{
    ll ans=0;
    while(x)
    {
        ans=max(ans,sum[x]);//cout<<"x"<<x<<endl;
        x-=lowbit(x);
    }
    return ans;
}
int main()
{
    ll o=read();
    while(o--)
    {
        mx=0;
        memset(sum,0,sizeof(sum));//清零 
        memset(a,0,sizeof(a));
        n=read();
        for(ll i=1;i<=n;i++)
            a[i]=read(),
            mx=max(mx,a[i]);
        insert(a[1],1);//先把第一个加入,因为第一个的dp[1]总是1 
        ll ans=0;
        for(ll i=2;i<=n;i++)
        {
//            if(a[i]==5)
//                cout<<sum[4]<<endl改代码的艰难痕迹 
            ll x=findout(a[i]);
            ans=max(ans,x+1);
//            cout<<a[i]<<" "<<x<<endl;
            insert(a[i],x+1);
        }
        printf("%lld\n",ans);//就这么多了,没什么讲的 
    }
}

猜你喜欢

转载自www.cnblogs.com/wzx-RS-STHN/p/13381782.html