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;
#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;
}