注意:最长不减子序列的个数 = = 最长递减子序列的长度
最长不增子序列的个数 = = 最长递增子序列的长度
最长递增子序列的个数 = = 最长不增子序列的长度
最长递减子序列的个数 = = 最长不减子序列的长度
#include <iostream>
using namespace std;
#define N 1001
int data[N],f[N],dp[N],p[N],e=0;//data数组保存数据,dp有序序列的长度数组,f辅助数组,p保存路径
int bsearch(int *f,int size,int t)//二分查找,复杂度logn
{ //找出f数组中第一个比t大的数的下标
int l=0,r=size-1;
while(l<=r)
{
int mid=(l+r)/2;
if(t>f[mid-1]&&t<=f[mid])return mid;//最长不减子序列,换为>=&&<,递减,<&&>=,不增,<=&&>
else if(t<f[mid])r=mid-1;
else l=mid+1;
}
return -1;
}
int LIS(int *data,int n)
{
int i,j,size =1;//size是f数组的大小
f[0]=data[0];dp[0]=1;p[0]=-1;//第一个点
for(i=1;i<n;i++)
{
//如果data比f数组中最小的还小,则以该点为末尾点的数组的长度为0+1=1;f数组中数据是递增的且保存的是data中数据最小的元素集合
if(data[i]<=f[0])j=0;//最长不减子序列,<,递减,>=,不增,>
else if(data[i]>f[size-1])j=size++;//最长不减子序列,>=,递减,<,不增,<=
else j=bsearch(f,size,data[i]);// 找出f数组中第一个比data[i]大的元素的下标j,则以该点为末尾点的数组的长度为j+1;
f[j]=data[i];dp[i]=j+1;
//若求路径则取消注释
// if(j==0)p[i]=-1;//求p,求最长有序序列的长
// else
// {
// for(int k=0;k<i;k++)
// {
// if(data[k]==f[j-1])
// {
// p[i]=k;
// }
// }
// }
// if(dp[i]==size)e=i; //保存长度最长的有序序列的末尾点的下标
}
return size;
}
void printLIS(int e)//输出路径
{
if(p[e]!=-1)printLIS(p[e]);
cout<<data[e]<<endl;
}