树状数组求LIS(最长上升子序列)

Posted live4m

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了树状数组求LIS(最长上升子序列)相关的知识,希望对你有一定的参考价值。

树状数组求LIS

优点:

同样是O(nlogn)的复杂度
二分做法只能计算出当前序列的LIS
而树状数组可以计算出以每一个a(i)为结尾的LIS

且二分的做法只能计算出答案,无法得到具体方案。

做法:

树状数组维护前缀max

设以a(i)结尾的LIS为F(i)
树状数组的c(x)存放以x为结尾的LIS,注意这里的x是一个具体的值,而不是下标,即c(a(i))=F(i)
每次插入一个新的数a(i)的时候,F(i)=ask(a(i))+1,然后插入,add(a(i),F(i))

原理是树状数组的查询ask(a(i))可以O(logn)计算出前i-1个数中小于a(i)中的F(i)的最大值。

另外:c(i)代表以a(i)为结尾的LIS,数组c的大小取决于a(i)的最大值,当数据范围大的时候需要先离散化


AtCoder2827 LIS

题意:

给长度为n的数组,计算LIS。
数据范围:n<=1e5

code:

#include<bits/stdc++.h>
using namespace std;
const int maxm=1e5+5;
int c[maxm];
int f[maxm];
int a[maxm];
int lowbit(int i)
    return i&-i;

void add(int i,int t)
    while(i<maxm)
        c[i]=max(c[i],t);
        i+=lowbit(i);
    

int ask(int i)
    int ans=0;
    while(i)
        ans=max(ans,c[i]);
        i-=lowbit(i);
    
    return ans;

signed main()
    int n;
    cin>>n;
    for(int i=1;i<=n;i++)
        cin>>a[i];
    
    for(int i=1;i<=n;i++)
        f[i]=ask(a[i])+1;
        add(a[i],f[i]);
    
    int ans=0;
    for(int i=1;i<=n;i++)
        ans=max(ans,f[i]);
    
    cout<<ans<<endl;
    return 0;


以上是关于树状数组求LIS(最长上升子序列)的主要内容,如果未能解决你的问题,请参考以下文章

BZOJ3173: [Tjoi2013]最长上升子序列(树状数组)

最长上升子序列 (LIS) 详解+例题模板 (全)(转)

最长上升子序列 (LIS) 详解+例题模板 (全)(转)

18.10.9 不好做的最长上升子序列(nlogn树状数组解LIS)

[树状数组] aw3662. 最大上升子序列和(LIS优化+树状数组+离散化+好题+aw周赛003_3)

BZOJ3173: [Tjoi2013]最长上升子序列