題目1533:最長上升子序列

題目描述:
給定一個整型數組, 求這個數組的最長嚴格遞增子序列的長度。 譬如序列1 2 2 4 3 的最長嚴格遞增子序列爲1,2,4或1,2,3.他們的長度爲3。
輸入:
輸入可能包含多個測試案例。
對於每個測試案例,輸入的第一行爲一個整數n(1<=n<=100000):代表將要輸入的序列長度
輸入的第二行包括n個整數,代表這個數組中的數字。整數均在int範圍內。
輸出:
對於每個測試案例,輸出其最長嚴格遞增子序列長度。
樣例輸入:
4
4 2 1 3
5
1 1 1 1 1
樣例輸出:
2
1
原來是用動態規劃的方式,假設現在在V[k],這個數能湊齊的最長子序列爲F[k],從V[0]~v[k-1]依次找出小於v[k]的數,此時F[k]=max{F[k],F[i]+1},i=0,1,2,………k-1。結果超時了,於是找了其他大神的做法,參考http://www.cnblogs.com/liyongmou/archive/2010/07/11/1775341.html

最長上升子序列問題:
舉例:原序列爲1,5,8,3,6,7
棧爲1,5,8,此時讀到3,則用3替換5,得到棧中元素爲1,3,8, 再讀6,用6替換8,得到1,3,6,再讀7,得到最終棧爲1,3,6,7 ,最長遞增子序列爲長度4。
所以有了如下做法:

#include<stdio.h>
using namespace std;
int v[100001];
int main()
{
    int n;
    while(scanf("%d",&n)!=EOF)
    {
        if(n<=0)
            return 0;
        int j=0,i;
        int qian,hou,mid;
        for(i=0;i<n;i++)
        {
            scanf("%d",v+j);//將當前輸入值放在數組末尾
            qian=0;
            hou=j;
            if(j==0||(j>0&&v[j]>v[j-1]))//如果當前值剛好大於數組最大值,什麼也不做,將數組長度++
                j++;
            else
            {
              while(hou>qian)//二分法尋找數組中最小大於或等於當前值temp的數的下標
              {
                mid=(qian+hou)/2;
                if(v[j]<=v[mid])//等號不可或缺,畢竟會有相同的數,等號可以讓數組不會出現1 2 2 2 3這種錯誤的情況
                    hou=mid;
                else
                    qian=mid+1;
              }
               v[hou]=v[j];
            }
        }
        printf("%d\n",j);
    }
    return 0;
}
/**************************************************************
    Problem: 1533
    User: 午夜小白龍
    Language: C++
    Result: Accepted
    Time:170 ms
    Memory:1412 kb
****************************************************************/

http://ac.jobdu.com/showsource.php?sid=1858627

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章