HDU5489 Removed Interval(动态规划)

一个长度为n的序列,删除任意长度为l的连续子序列后,求剩下的序列的最长公共子序列。

 

先求出以第i个元素为开始的LIS的长度,再一次循环,对所要求的结果更新

 

#include<iostream>
#include<cstdio>
#include<string>
#include<cstring>
#include<cstdlib>
#include<queue>
#include<vector>
#include<algorithm>
const int INF = 0x3F3F3F3F;
using namespace std;
typedef long long LL;
const int N = 200008;
int a[N];
int lis[N], dp[N];

int main(){
    int n, l;
    int t;
    cin>>t;
    for(int t1 = 1; t1 <= t; t1++){
        scanf("%d %d",&n, &l);
        for(int i = 0; i < n; i++){
            scanf("%d", &a[i]);
        }
        a[n] = INF;
        int pos = 0 , len = 1;
        lis[n] = 0;
        lis[n - 1] = 1;
        dp[0] = -a[n - 1];
        for(int i = n - 2; i >= 0; i--){
            pos = lower_bound(dp, dp + len, -a[i]) - dp;
            dp[pos] = -a[i];
            if(pos == len){
                len++;
            }
            lis[i] = pos + 1;
        }
        int ans = lis[l];
        len = 1;
        dp[0] = a[0];
        for(int i = 1, j = l; j < n; i++, j++){
            int tp = lis[j + 1];
            pos = lower_bound(dp, dp + len, a[j + 1]) - dp;
            tp += pos;
            ans = max(ans, tp);

            pos = lower_bound(dp, dp + len, a[i]) - dp;
            dp[pos] = a[i];
            if(pos == len){
                len++;
            }
    }


    printf("Case #%d: %d\n", t1, ans);
    }
    return 0;

} 

posted @ 2016-07-26 21:04  vwirtveurit  阅读(194)  评论(0编辑  收藏  举报