题解:P16350 「Gensokyo OI Round 1」隙间插曲
神秘 dp,蓝?
注意到既可以在开头删又可以在结尾删比较麻烦。但因为最终序列中的元素个数
考虑倒推。设
显然
对于
一种是保留它,此时得到的值为
另一种是删除它。注意到每个元素被删除都需要且仅需要它右边直到某个元素全部被删除,设这是第
所以剩下的问题就是
如果这个元素非零,则
否则,考虑原先最右边一个到目前为止还不可能被删除的元素(代码中用
这次遍历可以与输入同时进行,完成后即可开始刚才的 dp。
总时间复杂度
#include <iostream>
using namespace std;
int b[1001],c[1001];
long long dp[1002][1001];
int main() {
int n,m=0,x=0,a,i,j;
long long ans=0;
cin>>n;
for(i=1;i<=n;i++) {
cin>>a;
if(a) b[++m]=a;else {x++;for(j=m;j&&c[j];j--);c[j]=m;}
}
x=m-x;
for(j=1;j<=x;j++) dp[m+1][j]=-1e18;
for(i=m;i;i--) {
dp[i][0]=-1e18;for(j=1;j<=x;j++) dp[i][j]=dp[i+1][j-1]+b[i];
if(c[i]) for(j=0;j<=x;j++) dp[i][j]=max(dp[i][j],dp[c[i]+1][j]);
ans=max(ans,dp[i][x]);
}
cout<<ans;
return 0;
}
:::: AC 记录。 ::::info[闲话] 感谢善良的出题人放的 subtask 3 拯救了我的分数。 ::::