2011-08-28 07:14:52Morris

d242. Q481: What Goes Up

d242. Q481: What Goes Up

內容 :

Q481: What Goes Up

寫一個程式從一連串的整數序列中選出最長的嚴格遞增子序列(strictly increasing subsequence)。例如:在 1, 3, 2, 2, 4, 0 中最長的嚴格遞增子序列為 1,3, 4 或者 1, 2, 4。

輸入說明 :

只有一組測試資料。

輸入包含一連串的整數(大約500000個),每個整數一列。請參考Sample Input。

輸出說明 :

首先輸出一列最長的嚴格遞增子序列的長度是多少。然後一列僅含有一個減號(dash character, '-')。然後接下來為這個最長的嚴格遞增子序列的內容,每個整數一列。

如果有不止一個最長的嚴格遞增子序列,請輸出在輸入中最後出現的。例如在 1, 3, 2, 2, 4, 0 中,應該輸出 1, 2, 4 而不是 1, 3, 4。

請參考Sample Output。

範例輸入 :

-7
10
9
2
3
8
8
1


範例輸出 :

4
-
-7
2
3
8

提示 :

出處 :

UVA 481 (管理:nanj0178)



作法 : Greedy 的 LIS
參照 http://www.csie.ntnu.edu.tw/~u91029/LongestIncreasingSubsequence.html

/**********************************************************************************/
/*  Problem: d242 "Q481: What Goes Up" from UVA 481                               */
/*  Language: C                                                                   */
/*  Result: AC (36ms, 1411KB) on ZeroJudge                                        */
/*  Author: morris1028 at 2011-08-27 19:27:34                                     */
/**********************************************************************************/


#include<stdio.h>
#include<stdlib.h>
int A[500000], pos[500000], LIS[500000];
int BinarySearch(int l, int r, int v) {
    int m, L = r;
    do {
        m = (l+r)/2;
        if(LIS[m] >= v) {
            if(m == 0)
                return m;
            else {
                if(LIS[m-1] < v)
                    return m;
                else
                    r = m-1;
            }
        } else {
            l = m+1;
        }
    }while(l <= r);
    return L+1;
}
int DP_LIS(int n) {
    int a, b, LIS_L = -1, set, Ans = 0;
    for(a = 0; a < n; a++) {
        set = BinarySearch(0, LIS_L, A[a]);
        LIS[set] = A[a], pos[a] = set;
        if(set >= LIS_L) LIS_L = set;
    }
    for(a = 0; a < n; a++)
        Ans = Ans > pos[a] ? Ans : pos[a];
    printf("%d\n-\n", Ans+1);
    LIS_L = Ans;
    for(a = n-1; a >=0; a--)
        if(pos[a] == Ans)
            LIS[Ans] = A[a], Ans--;
    for(a = 0; a <= LIS_L; a++)
        printf("%d\n", LIS[a]);
}
main() {
    int in = 0;
    while(scanf("%d", &A[in]) == 1)
        in++;
    DP_LIS(in);
    return 0;
}