[P16350] 「Gensokyo OI Round 1」隙间插曲 题解
aeiouaoeiu · · 题解
删开头是简便的,视为删除一个前缀即可,但是删结尾可能会出现跳跃的情况,比较麻烦。但可以发现,如果倒序操作,可以将删除结尾视作积累一个删除势能,在势能降为
于是可以将势能加入状态,倒序 dp。设
总复杂度
:::info[code]
#include<bits/stdc++.h>
#define pb emplace_back
#define mp make_pair
using namespace std;
typedef long long ll;
typedef double db;
const ll maxn=1007,ee=1e18,p=1e9+7;
ll n,a[maxn],m,b[maxn],d[maxn],val[maxn],f[maxn][maxn],ans,tot;
int main(void){
//freopen("data.in","r",stdin);
//freopen("data.out","w",stdout);
ios::sync_with_stdio(0);
cin>>n;
for(ll i=1;i<=n;i++){
cin>>a[i],tot+=a[i],d[i]=d[i-1];
if(a[i]) b[++m]=a[i],d[i]++;
else d[i]--;
}
memset(f,0x3f,sizeof(f));
f[0][0]=0;
ll c=0;
for(ll i=n;i>=1;i--){
if(a[i]==0){
c++;
for(ll j=c;j>=0;j--)for(ll k=c-j;k>=0;k--){
f[j][k]=min(j?f[j-1][k]:ee,k?f[j][k-1]:ee);
if(d[i]<k){
if(j) f[j][k]=ee;
else f[j][k]=(k?f[j][k-1]:ee);
}
}
}else{
for(ll j=0;j<=c;j++)for(ll k=c-j;k>=0;k--){
if(j) f[j][k]=f[j+1][k]+a[i];
else f[j][k]=min(f[j][k],f[j+1][k]+a[i]);
}
}
}
for(ll i=0,s=0;i<=m;i++){
ans=max(ans,tot-f[0][i]-s),s+=b[i+1];
}
cout<<ans<<"\n";
return 0;
}
:::