codeforces425C http://codeforces.com/contest/425/problem/C 题意:两数列a[],b[],进行若干轮操作,每次操作花费e,
题意:两数列a[],b[],进行若干轮操作,每次操作花费e,
将a的一个前缀和b的一个前缀(两前缀的最后一个数字必须相同)删除,并得到虚拟1元,
最后的一次操作是将剩下的a[],b[]全部清空,花费是之前把a[],b[]删除的总数字个数,使得虚拟ans元变为真实ans元。
sol:首先有个很明显得暴力,就是n2求lcs
#include <bits/stdc++.h> using namespace std; typedef int ll; inline ll read() { ll s=0; bool f=0; char ch=' '; while(!isdigit(ch)) {f|=(ch=='-'); ch=getchar();} while(isdigit(ch)) {s=(s<<3)+(s<<1)+(ch^48); ch=getchar();} return (f)?(-s):(s); } #define R(x) x=read() inline void write(ll x) { if(x<0) {putchar('-'); x=-x;} if(x<10) {putchar(x+'0'); return;} write(x/10); putchar((x%10)+'0'); } #define W(x) write(x),putchar(' ') #define Wl(x) write(x),putchar(' ') const int N=1005; int n,m,up,cost; int a[N],b[N],dp[N][N]; int main() { freopen("codeforces425C_data.in","r",stdin); int i,j; R(n); R(m); R(up); R(cost); for(i=1;i<=n;i++) R(a[i]); for(i=1;i<=m;i++) R(b[i]); for(i=0;i<=n;i++) { for(j=0;j<=m;j++) { dp[i][j]=0; if(i==j&&i==0) continue; if(i) dp[i][j]=dp[i-1][j]; if(j) dp[i][j]=max(dp[i][j],dp[i][j-1]); if(a[i]==b[j]) { dp[i][j]=max(dp[i][j],dp[i-1][j-1]+1); } } } int ans=0; for(i=1;i<=n;i++) for(j=1;j<=m;j++) if(dp[i][j]*cost+i+j<=up) ans=max(ans,dp[i][j]); Wl(ans); return 0; }
但是显然挂了,所以我就写了一个树状数组求lcs,然后告诉我相同数字多次出现。。。
考虑一种dp,dp[i,j]表示长度为i的公共子序列,a串匹配到j时b的最小位置
至于那个位置,万能的STL
/* 题意:两数列a[],b[],进行若干轮操作,每次操作花费e, 将a的一个前缀和b的一个前缀(两前缀的最后一个数字必须相同)删除,并得到虚拟1元, 最后的一次操作是将剩下的a[],b[]全部清空,花费是之前把a[],b[]删除的总数字个数,使得虚拟ans元变为真实ans元。 */ #include <bits/stdc++.h> using namespace std; typedef int ll; inline ll read() { ll s=0; bool f=0; char ch=' '; while(!isdigit(ch)) {f|=(ch=='-'); ch=getchar();} while(isdigit(ch)) {s=(s<<3)+(s<<1)+(ch^48); ch=getchar();} return (f)?(-s):(s); } #define R(x) x=read() inline void write(ll x) { if(x<0) {putchar('-'); x=-x;} if(x<10) {putchar(x+'0'); return;} write(x/10); putchar((x%10)+'0'); } #define W(x) write(x),putchar(' ') #define Wl(x) write(x),putchar(' ') const int N=100005,inf=0x3f3f3f3f; int n,m,up,cost; int a[N],b[N]; int dp[305][N];//dp[i,j]表示长度为i的公共子序列,a串匹配到j时b的最小位置 vector<int>Pos[N]; #define PB push_back int main() { freopen("codeforces425C_data.in","r",stdin); int i,j,ans=0; R(n); R(m); R(up); R(cost); for(i=1;i<=n;i++) R(a[i]); for(i=1;i<=m;i++) { R(b[i]); Pos[b[i]].PB(i); } for(i=1;i<=n;i++) Pos[a[i]].PB(inf); for(i=1;i<=up/cost;i++) { dp[i][0]=inf; for(j=1;j<=n;j++) { dp[i][j]=min(inf,dp[i][j-1]); int oo=lower_bound(Pos[a[j]].begin(),Pos[a[j]].end(),min(dp[i-1][j-1]+1,inf))-Pos[a[j]].begin(); if(oo>m) continue; dp[i][j]=min(dp[i][j],Pos[a[j]][oo]); if(i*cost+dp[i][j]+j<=up) ans=i; } } Wl(ans); return 0; }