最长上升子序列

【题目描述】

给定一个数列,询问此数列的LIS长度。

【输入描述】

第一行输入一个正整数n(n <= 100000),表示数列长度;

第二行输入n个数,表示原始数列。

【输出描述】

输出一个数,表示答案。

【输入样例】

3

3 1 2

【输出样例】

2

源代码:

#include<cstdio>
int n,Ans=1,i[100001],Stack[100001];
int Search(int T) //二分查找。
{
    int Left=1,Right=Ans;
    while (Left<=Right)
    {
        int Mid=(Left+Right)>>1;
        if (T>Stack[Mid]&&T<=Stack[Mid+1])
          return Mid;
        else
          if (T>Stack[Mid])
            Left=Mid+1;
          else
            Right=Mid-1;
    }
    return 0;
}
int main() //O(nlogn)的神威!
{
    scanf("%d",&n);
    for (int a=1;a<=n;a++)
      scanf("%d",&i[a]);
    int T;
    Stack[1]=i[1]; //Stack[]是一个单调栈。
    for (int a=2;a<=n;a++)
    {
        if (Stack[Ans]<i[a])
          T=++Ans;
        else
          T=Search(i[a])+1;
        Stack[T]=i[a];
    }
    printf("%d",Ans); //单调栈的长度即为LIS长度。
    return 0;
}

/*
    为什么这样是正确的呢?
    当无法更新单调栈长度时,将此元素的作用发挥到了最大——替换掉刚好比它大的那个数,其实这是一个贪心。
*/
posted @ 2016-10-26 14:36  前前前世。  阅读(209)  评论(0编辑  收藏  举报