LIS变种。
那么怎么变种。
f(i,j)前i个变j次.最大的lis值。
转移:f(x,y)=max:sigma(f(i,j)a[i]+j<f[x]+f[y])
好了:既然如此时间复杂度为:n^2k显然不行。
这时候观察发现:j单调a[i]+j自然单调,于是形成区间。
那么就简单了。还记得CDOJ的DP专练大赛吗?柱爷抢银行。线段树维护区间最大值。
但是!这个更难。
二位BIT维护区间最大值:复杂度:n*k*logn*logk但由于k小,实际只挂上一个log。
#include<iostream>
#include<cstdio>
#include<algorithm>
using namespace std;
int n,k;
int a[12000]={0};
int f[12000][600]={0};
int T[6010][610]={0};
inline int lowbit(int x){
return x&(-x);
}
void update(int x,int y,int val){
for(int i=x;i<=6000;i+=lowbit(i)){
for(int j=y;j<=600;j+=lowbit(j)){
T[i][j]=max(T[i][j],val);
}
}
}
int Quary(int x,int y){
int ret=0;
for(int i=x;i;i-=lowbit(i)){
for(int j=y;j;j-=lowbit(j)){
ret=max(ret,T[i][j]);
}
}
return ret;
}
int main(){
scanf("%d%d",&n,&k);
for(int i=1;i<=n;i++){
scanf("%d",&a[i]);
}
for(int i=1;i<=n;i++){
for(int j=k;j>=0;j--){
int t=Quary(a[i]+j,j+1)+1;
// cout<<i<<" "<<j<<" "<<t<<endl;
f[i][j]=t;
update(a[i]+j,j+1,t);
}
}
int ans=0;
for(int i=1;i<=n;i++){
for(int j=0;j<=k;j++){
// cout<<i<<" "<<j<<" "<<f[i][j]<<endl;
ans=max(ans,f[i][j]);
}
}
cout<<ans;
}