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]);
     }
}
 
                     
                    
                 
                    
                
 
                
            
         
         浙公网安备 33010602011771号
浙公网安备 33010602011771号