1. 程式人生 > >ZZULI - 程式設計師的揹包(最長上升子序列+二分優化)

ZZULI - 程式設計師的揹包(最長上升子序列+二分優化)

題目連結:http://acm.zzuli.edu.cn/problem.php?id=2485
時間限制: 1 Sec  記憶體限制: 256 MB

題目描述

眾所周知,每個程式設計師都有一個揹包,裡邊裝著膝上型電腦(才不是為了隨時改bug呢),耳機,移動電源,switch等。現在,L同學有一個揹包,這個揹包比較奇特,首先它的空間特別大,其次呢,它裝東西要遵循一個規則:裝的東西的重量只能遞增。畢竟這是個四次元口袋嘛,哈哈。現在,L同學面前有一個傳送帶,傳送帶上會有很多東西依次傳過來,L同學只可以選擇是否把這個物品放進四次元揹包。L同學用預知能力得知了這些物品的重量(這裡假設質量可能為負質量),那麼他最多能往揹包裡裝多少東西呢?

輸入

第1行:1個數N,N為物品的數量(2 <= N <= 50000)
第2 - N + 1行:每行1個數,對應物品的重量(-10^9 <= S[i] <= 10^9)

輸出

最多能裝進揹包的物品的數量

樣例輸入

8
5
1
6
8
2
4
5
10

樣例輸出

5

解題思路

讀懂題意就能知道,這是一道最長上升子序列的模板題,套一下最長上升子序列的優化模板就行了。

#include <stdio.h>
#include <string.h>
int a[50010], dp[50010];
int search(int x, int l, int r) {
    while (l < r) {
        int mid = l + (r - l) / 2;
        if (dp[mid] >= x)
            r = mid;
        else l = mid + 1;
    }
    return l;
}
int LIS(int a[], int n) {
    int p, len = 1;
    memset(dp, 0, sizeof dp);
    dp[0] = a[0];
    for(int i = 1; i < n; i++) {
        if (a[i] >= dp[len - 1])
            dp[len++] = a[i];
        else {
            p = search(a[i], 0, len - 1);
            dp[p] = a[i];
        }
    }
    return len;
}
int main() {
    int n;
    while (~scanf("%d", &n)) {
        for (int i = 0; i < n; i++)
            scanf("%d", &a[i]);
        printf("%d\n", LIS(a, n));
    }
    return 0;
}