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;
}

 

posted @ 2015-01-29 16:56  miao_a_miao  阅读(468)  评论(0编辑  收藏  举报