HDU 5489 Removed Interval DP 树状数组

题意:

给一个长度为(N)的序列,要删除一段长为(L)的连续子序列,问所能得到的最长的(LIS)的长度。

分析:

(f(i))表示以(a_i)结尾的(LIS)的长度,设(g(i))表示以(a_i)结尾而且被删去一段长为(L)(LIS)的长度。
则有状态转移方程:

(g(i)=max( g(j) , f(j)_{j<i-L} ))

用树状数组维护一下。
我用二分也写了一遍,WA掉了,不知道怎么改。 = =||

#include <iostream>
#include <cstdio>
#include <cstring>
#include <algorithm>
using namespace std;

const int maxn = 100000 + 10;

int n, L;

int a[maxn], b[maxn];

int f[maxn], g[maxn];

int C1[maxn], C2[maxn];

inline int lowbit(int x) { return x & (-x); }

void Change(int* C, int x, int v) {
    while(x <= n) {
        C[x] = max(C[x], v);
        x += lowbit(x);
    }
}

int Query(int* C, int x) {
    int ans = 0;
    while(x) {
        ans = max(ans, C[x]);
        x -= lowbit(x);
    }
    return ans;
}

int main() {
    //freopen("in.txt", "r", stdin);

    int T; scanf("%d", &T);
    for(int kase = 1; kase <= T; kase++) {
        scanf("%d%d", &n, &L);
        for(int i = 1; i <= n; i++) {
            scanf("%d", a + i);
            b[i] = a[i];
        }
        sort(b + 1, b + 1 + n);
        for(int i = 1; i <= n; i++) a[i] = lower_bound(b + 1, b + 1 + n, a[i]) - b;

        memset(f, 0, sizeof(f));
        memset(g, 0, sizeof(g));
        memset(C1, 0, sizeof(C1));
        memset(C2, 0, sizeof(C2));

        int ans = 0;
        for(int i = L + 1; i <= n; i++) {
            g[i] = max(Query(C1, a[i] - 1), Query(C2, a[i] - 1)) + 1;
            ans = max(ans, g[i]);
            Change(C2, a[i], g[i]);
            f[i - L] = Query(C1, a[i - L] - 1) + 1;
            Change(C1, a[i - L], f[i - L]);
        }
        ans = max(ans, f[n - L]);   //可能是去掉最后L个

        printf("Case #%d: %d
", kase, ans);
    }

    return 0;
}

原文地址:https://www.cnblogs.com/AOQNRMGYXLMV/p/4867615.html