LIS的nlogn
nlogn老忘,开个帖记录一下
开一个栈,每次取栈顶元素top和读到的元素temp做比较,如果temp > top 则将temp入栈;如果temp < top则二分查找栈中的比temp大的第1个数,并用temp替换它。 最长序列长度即为栈的大小top。
例如对2 1 5 3 6 4 8 9 7
每一步的结果
1. 2
2. 1
3. 1 5
4. 1 3
5. 1 3 6
6. 1 3 4
7. 1 3 4 8
8. 1 3 4 8 9
9. 1 3 4 7 9
最后的13479并不是LIS,而是对应LIS长度的最小末尾,记录栈顶元素即可求出对应LIS序列
const int MAXN=500010; int a[MAXN],b[MAXN]; //用二分查找的方法找到一个位置,使得num>b[i-1] 并且num<b[i],并用num代替b[i] int Search(int num,int low,int high) { int mid; while(low<=high) { mid=(low+high)/2; if(num>=b[mid]) low=mid+1; else high=mid-1; } return low; } int DP(int n) { int i,len,pos; b[1]=a[1]; len=1; for(i=2;i<=n;i++) { if(a[i]>=b[len])//如果a[i]比b[]数组中最大还大直接插入到后面即可 { len=len+1; b[len]=a[i]; } else//用二分的方法在b[]数组中找出第一个比a[i]大的位置并且让a[i]替代这个位置 { pos=Search(a[i],1,len); b[pos]=a[i]; } } return len; }