标签:删除 $2 bst 直接 就是 expec cpp 位置 子串
“unexpected, right?”大概可以翻译成“没想到吧!”
题意:给两个序列$w_{1\cdots n}$和$v_{1\cdots n}$,你可以多次删除$w$的子串$w_{l\cdots r}$并获得$v_{r-l+1}$分,被删除的$w_{l\cdots r}$要满足:对$\forall i\in[l,r-1]$有$|w_i-w_{i+1}|=1$且对$\forall i\in[l+1,r-1]$有$2w_i-w_{i-1}-w_{i+1}\geq0$,问最多获得多少分
说白了就是只能删(连续上升的/连续下降的/先连续上升后连续下降的)
设$f_{i,j}$表示删完$w_{i\cdots j}$的最大分数,$g_{i,j,0}$表示把$w_{i\cdots j}$删至连续上升的最大分数,$g_{i,j,1}$表示把$w_{i\cdots j}$删至连续下降的最大分数
$g_{i,j,0}=\max\left\{[w_{j-1}+1=w_j]g_{i,j-1,0},\mathop\max\limits_{k=i}^{j-2}\left\{[w_k+1=w_j](g_{i,k,0}+f_{k+1,j-1})\right\}\right\}$(可以直接在$w_{i\cdots j-1}$后加上$w_j$,也可以从中间选一个位置$k$,把$w_{k+1\cdots j-1}$删完,再接上$w_j$)
$g_{i,j,1}=\max\left\{[w_{j-1}-1=w_j]g_{i,j-1,1},\mathop\max\limits_{k=i}^{j-2}\left\{[w_k-1=w_j](g_{i,k,1}+f_{k+1,j-1})\right\}\right\}$(同理)
$f_{i,j}=\max\left\{\begin{matrix}[1\leq w_j-w_i+1\leq n](g_{i,j,0}+v_{w_j-w_i+1})\\ [1\leq w_i-w_j+1\leq n](g_{i,j,1}+v_{w_i-w_j+1})\\\mathop\max\limits_{k=i}^{j-1}\left\{f_{i,k}+f_{k+1,j}\right\}\\\mathop\max\limits_{k=i+1}^{j-1}\left\{[1\leq2w_k-w_i-w_j+1\leq n]g_{i,k,0}+g_{k,j,1}+v_{2w_k-w_i-w_j+1}\right\}\end{matrix}\right\}$(可以先删成连续上升或连续下降再直接删除,也可以先删$w_{i\cdots k}$再删$w_{k+1\cdots j}$,还可以先删成上升下降再整段删除)
最后再DP求出最大的$[i,j]$互不相交的$f_{i,j}$之和即可
#include<stdio.h> const int inf=100000000; int v[410],w[410],f[410][410],g[410][410][2],ans[410]; void max(int&a,int b){ if(a<b)a=b; } int main(){ int n,i,j,k; scanf("%d",&n); for(i=1;i<=n;i++)scanf("%d",v+i); for(i=1;i<=n;i++)scanf("%d",w+i); for(i=1;i<=n;i++){ for(j=1;j<=n;j++)f[i][j]=g[i][j][0]=g[i][j][1]=-inf; } for(i=n;i>0;i--){ f[i][i]=v[1]; g[i][i][0]=g[i][i][1]=0; for(j=i+1;j<=n;j++){ for(k=i;k<j-1;k++){ if(w[k]+1==w[j])max(g[i][j][0],g[i][k][0]+f[k+1][j-1]); } if(w[j-1]+1==w[j])max(g[i][j][0],g[i][j-1][0]); } for(j=i+1;j<=n;j++){ for(k=i;k<j-1;k++){ if(w[k]-1==w[j])max(g[i][j][1],g[i][k][1]+f[k+1][j-1]); } if(w[j-1]-1==w[j])max(g[i][j][1],g[i][j-1][1]); } for(j=i;j<=n;j++){ if(w[j]-w[i]+1>0&&w[j]-w[i]+1<=n)max(f[i][j],g[i][j][0]+v[w[j]-w[i]+1]); if(w[i]-w[j]+1>0&&w[i]-w[j]+1<=n)max(f[i][j],g[i][j][1]+v[w[i]-w[j]+1]); for(k=i;k<j;k++)max(f[i][j],f[i][k]+f[k+1][j]); for(k=i+1;k<j;k++){ if(2*w[k]-w[i]-w[j]+1>0&&2*w[k]-w[i]-w[j]+1<=n)max(f[i][j],g[i][k][0]+g[k][j][1]+v[2*w[k]-w[i]-w[j]+1]); } } } for(i=1;i<=n;i++){ ans[i]=ans[i-1]; for(j=0;j<i;j++)max(ans[i],ans[j]+f[j+1][i]); } printf("%d",ans[n]); }
标签:删除 $2 bst 直接 就是 expec cpp 位置 子串
原文地址:https://www.cnblogs.com/jefflyy/p/8832147.html