小知识
本质上为二分查找所以序列必须升序
(定义序列大小后降序也可以)
lower_bound会找出序列中第一个大于等于x的数
upper_bound会找出序列中第一个大于x的数
差别在于是否包含等于x的数
用法:
lower_bound(a,a+n,x);//在a[]中找到第一个不大于x的数
lower_bound(a,a+n,x,cmp);//实际上还可以加上比较函数
lower_bound(a,a+n,x,greater<int>());//这样就改为降序序列
该函数的返回值是一个指针
所以当用这个指针减去数组名即为查找数的数组下标
int p=lower_bound(a,a+n,x)-a;
原:求最长上升子序列
const int BN=1e5+5;
int BiSearch(int b[],int n,int w);
int LIS(int a[],int n)
{
int len=1;
int b[BN];
b[0]=a[0];
for(int i=1;i<n;i++)
{
if(a[i]>b[len-1])
b[len++]=a[i];
else
{
int p=BiSearch(b,len,a[i]);
b[p]=a[i];
}
}
return len;
}
int BiSearch(int b[],int n,int w)
{
int l=0,r=n-1,mid;
while(l<=r)
{
mid=l+(r-l)/2;
if(b[mid]<w)l=mid+1;
else if(b[mid]>w)r=mid-1;
else return mid;
}
return l;
}
简化后:
const int BN=1e5+5;
int LIS(int a[],int n)
{
int len=1;
int b[BN];
b[0]=a[0];
for(int i=1;i<n;i++)
{
if(a[i]>b[len-1])
b[len++]=a[i];
else
{
int p=lower_bound(b,b+len,a[i])-b;
b[p]=a[i];
}
}
return len;
}
后记:
如果想求降序就将函数改为
int p=lower_bound(b,b+len,a[i],greater<int>())-b;
如果想求最长非递增子序列就将函数改为
int p=upper_bound(b,b+len,a[i])-b;