hdu5125 magic balls BIT求LIS

分析:我們可以用dp[i][j]表示i爲結尾的使用了j點體力的最大值,因爲分a和b,所以再加1維,dp[i][j][0]表示a,dp[i][j][1]表示b,然後狀態轉移方程是這樣的

dp[i]j[j][0] = max{dp[k][j][0], k < i,a[k] < a[i]}, max(dp[k][j][1], k < i, b[k] < a[i]);

dp[i][j][1] = max{dp[k][j-1][0], k < i,a[k] < b[i]}, max(dp[k][j-1][1], k < i, b[k] < b[i]);

但是這樣時間複雜度是指數級的

然後我們可以用把a,b數組離散化後用BIT記錄使用了j點體力的最大值,先查詢,然後更新BIT,這樣就變成了n*m*logn,然後注意的是循環的順序,外循環是從0到n,

內循環從m到0而不是從0到m。舉例:a[0] = 1, b[0] = 2, 那麼在內圈從0循環到1的時候b[0] 會利用a[0]的值擴大LIS,而這是錯誤的,a[0]和b[0]不可同時存在的。

#include<cstdio>
#include<algorithm>
#include<cstring>
using namespace std;
const int N = 1009;
int nn;
int a[N],b[N];
int h[N * 2];
struct BIT{
    int c[2*N];
    int lowbit(int x){return x & -x;}
    void update(int x, int k){
        while(x <= nn){
            c[x] = max(c[x], k);
            x += lowbit(x);
        }
    }
    int query(int x){
        int ret = 0;
        while(x > 0){
            ret = max(ret ,c[x]);
            x -= lowbit(x);
        }
        return ret;
    }
}t[N];
int main(){
    int T;scanf("%d", &T);
    while(T--){
        int m, n;
        scanf("%d%d", &n, &m);
        for(int i = 0; i < n; i++){
            scanf("%d%d", &a[i], &b[i]);
            h[i] = a[i]; h[i+n] = b[i];
        }
        sort(h, h + 2 * n);
        nn = unique(h, h + 2 * n) - h;
        for(int i = 0; i < n; i++){
            a[i] = lower_bound(h, h + nn, a[i]) - h + 1;
            b[i] = lower_bound(h, h + nn, b[i]) - h + 1;
        }
        int ma = 1;
        memset(t, 0, sizeof(t));
        for(int i = 0; i < n; i++){
            for(int j = m; j >= 0; j--){
                int x1 = t[j].query(a[i] - 1) + 1;
                if(x1 > ma) ma = x1;
                t[j].update(a[i], x1);
                if(j > 0){
                    int x2 = t[j-1].query(b[i] - 1) + 1;
                    if(x2 > ma) ma = x2;
                    t[j].update(b[i], x2);
                }
            }
        }
        printf("%d\n", ma);
    }
    return 0;
}


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