d242: 00481 - What Goes Up

Tags: l.i.s, sequence


出處:https://zerojudge.tw/ShowProblem?problemid=d242
提交:https://zerojudge.tw/Submissions?problemid=d242&account=allllllan123456


問題:給你大約 500000 個整數,請求出最晚出現的最長 (嚴格) 遞增子序列 (longest increasing subsequence, LIS)。


解法:因為這題資料量較大,我們必須在 $\mathcal O(n\log_2n)$ 時間內完成,詳細作法可參考本站介紹最長遞增子序列的頁面。


 1#include <bits/stdc++.h>
 2using namespace std;
 3
 4// Ref: http://www.csie.ntnu.edu.tw/~u91029/LongestIncreasingSubsequence.html#3
 5
 6int n, dpLen, stackLen;
 7int arr[500000], dp[500000], len[500000], stacK[500000];
 8
 9int main() { ios_base::sync_with_stdio(false); cin.tie(nullptr); // IO 優化
10    while (cin >> arr[n]) {
11        int lb = 1, ub = dpLen, index = ub+1;
12        while (lb <= ub) {
13            int mid = (lb + ub) / 2;
14            if (dp[mid] >= arr[n]) ub = mid - 1, index = mid;
15            else lb = mid + 1;
16        }
17        len[n] = index;
18        dp[index] = arr[n++];
19        if (index > dpLen) dpLen = index;
20    }
21    cout << dpLen << "\n-\n";
22    for (n--; n>=0 && dpLen; n--)
23        if (len[n] == dpLen)
24            stacK[stackLen++] = arr[n],
25            dpLen--;
26    while (stackLen)
27        cout << stacK[--stackLen] << '\n';
28    return 0;
29}

no image