题意:
两组数字a和b 如果a[i]等于b[j] 则可将a[i]和b[j]前所有数字删掉 这种操作花费e体力 得到1元钱 或者一次删掉所有数字 这种操作花费等于曾经删除的所有数字个数 做完后得到所有钱 问 一共s体力 可以得到多少钱
思路:
dp+二分
由数据可知最多拿到300元钱 因此可以定义 dp[i][j]表示有i元钱时 b串删除到了j处时 a串删到的位置
状态转移为 dp[i][j] = lower_bound ( a[j] , dp[i-1][j-1] + 1 ) 意思是a[j]与dp[i-1][j-1]后的第一个相同的数字匹配 (可以这么做的原因是 保证第二种操作的花费最小 同时留下尽量多的数字供后面使用)
代码:
#include<cstdio> #include<cstring> #include<algorithm> #include<vector> using namespace std; #define N 100010 #define inf (1U<<31)-1 int n,m,s,e,ans; int a[N],b[N],dp[305][N]; vector<int> ed[N]; int main() { int i,j,k; scanf("%d%d%d%d",&n,&m,&s,&e); for(i=1;i<=n;i++) scanf("%d",&a[i]); for(j=1;j<=m;j++) { scanf("%d",&b[j]); ed[b[j]].push_back(j); } for(i=0;i<N;i++) ed[i].push_back(inf); memset(dp,-1,sizeof(dp)); memset(dp[0],0,sizeof(dp[0])); for(i=1;i<=s/e;i++) { for(j=1;j<=n;j++) { if(dp[i-1][j-1]!=-1) { dp[i][j]=dp[i][j-1]; k=lower_bound(ed[a[j]].begin(),ed[a[j]].end(),dp[i-1][j-1]+1)-ed[a[j]].begin(); k=ed[a[j]][k]; if(k==inf) continue; if(dp[i][j]==-1||dp[i][j]>k) dp[i][j]=k; if(dp[i][j]+j+i*e<=s) ans=max(ans,i); } } } printf("%d\n",ans); return 0; }
CodeForces 425C Sereja and Two Sequences
时间: 2024-12-27 20:51:39