LIS
LIS(Longest Increasing Subsequence)即最长上升子序列
给定一个序列,LIS是指其所有上升子序列中最长的一个
举个例子a={100,98,300,385,200,166}其最长上升子序列为{100,300,385}
朴素dp求法O(n*n)
算法描述
f[i]指以i为起点的LIS长度(视情况而定)。枚举起点,起点之后的原序列,如果a[j]>a[i]则f[i]可能是以j为起点的LIS+1,即f[i]=max(f[i],f[j]+1)。此处pre数组用来记录前驱,当前的i是由j转移过来的。
由于f[i]要由f[i+1---n]更新而来,所以枚举起点要倒序
Code
for(int i=n;i>0;--i){
for(int j=i;j<=n;++j){
if(a[j]>a[i]){
if(f[i]<f[j]+1){
pre[i]=j;f[i]=f[j]+1;
}
}
}
}
贪心+二分查找O(n*log(n))
算法描述
LIS数组记录可能的LIS,len表示LIS长度。扫描整个数组,如果a[i]大于LIS[len],则在末尾插入a[i];否则就在LIS中找到第一个比a[i]大的数,用a[i]将其替换,此处用到了stl upper_bound();
模拟
a={100,98,300,385,200,166}
i=1 LIS={100}
i=2 LIS={98}这里把100替换是为了让更多的数放进来,体现了贪心思想
i=3 LIS={98,300}
i=4 LIS={98,300,385}
i=5 LIS={98,200,385}
i=6 LIS={98,166,385}
很显然,这里求出的LIS是错误的,但是其保证了单调性,len是正确的
for(int i=1;i<=n;++i){
if(a[i]>LIS[len]){
LIS[++len]=a[i];
}
else{
int pos=upper_bound(LIS+1,LIS+len+1,a[i])-LIS;
LIS[pos]=a[i];//LIS不是正确的序列,但长度是正确的
}
}
关于upper_bound()和lower_bound()
upper_bound(start,end+1,data)。start为查找范围左端点的指针,end为查找范围右端点的指针,upper_bound会返回范围中第一个大于data的数的指针,如果找不到就返回end
lower_bound(start,end+1,data)。start为查找范围左端点的指针,end为查找范围右端点的指针,lower_bound会返回范围中第一个大于等于data的数的指针,如果找不到就返回end
重载
upper_bound(start,end+1,data,greater())
upper_bound会返回范围中第一个小于data的数的指针,如果找不到就返回end+1
lower_bound(start,end+1,data,greater())
lower_bound会返回范围中第一个小于等于data的数的指针,如果找不到就返回end+1
在结构体中的使用
重载一下小于号就行了
update 2022 1 25
树状数组维护LIS
x是原数组内某个值
c[x]定义为以x结尾的LIS长度
本质上是O(n^2)做法的优化,也就是说可以记录路径
代码可能是错的,退役了,先鸽着
void update(int x,int data){
for(int i=x;i<=n;i+=lowbit(x)){
if(c[x]+1>c[i]){
c[i]=c[x]+1;
pre[i]=x;
}
}
}
int query(int x){
int res=0;
for(int i=x;i;i-=lowbit(x)){
res=max(res,c[i]);
}
return res;
}
void work(){
n=read();
for(int i=1;i<=n;++i){
b[i]=a[i]=read();
}
//离散化
sort(b+1,b+n+1);
int len=unique(b+1,b+n+1)-b-1;
for(int i=1;i<=n;++i){
a[i]=lower_bound(b+1,b+len+1,a[i])-b;
}
for(int i=1;i<=len;++i)c[a[i]]=1;
for(int i=1;i<=len;++i){
c[a[i]]=query(a[i]-1);
update(a[i]);
}
}
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】凌霞软件回馈社区,博客园 & 1Panel & Halo 联合会员上线
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】博客园社区专享云产品让利特惠,阿里云新客6.5折上折
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· 【.NET】调用本地 Deepseek 模型
· CSnakes vs Python.NET:高效嵌入与灵活互通的跨语言方案对比
· DeepSeek “源神”启动!「GitHub 热点速览」
· 我与微信审核的“相爱相杀”看个人小程序副业
· Plotly.NET 一个为 .NET 打造的强大开源交互式图表库