codeforces425C

http://codeforces.com/contest/425/problem/C

题意:两数列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('\n')
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;
}
bl

但是显然挂了,所以我就写了一个树状数组求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('\n')
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;
}
View Code

猜你喜欢

转载自www.cnblogs.com/gaojunonly1/p/11312378.html