树状数组求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]最长上升子序列(树状数组)
18.10.9 不好做的最长上升子序列(nlogn树状数组解LIS)