• [8.16模拟赛] 玩具 (dp/字符串)


    题目描述

    儿时的玩具总是使我们留恋,当小皮还是个孩子的时候,对玩具更是情有独钟。小皮是一个兴趣爱好相当广泛且不专一的人,这这让老皮非常地烦恼。也就是说,小皮在不同时刻所想玩的玩具总是会不同,而有心的老皮也会尽量满足他的要求,帮他买一些新玩具。
    一开始小皮有一个长度为(N)的玩具序列 , 小皮的玩具可以用(a,b,c,...,z26)个英文字母表示,小皮可能会有(q)种需求,每种需求可以用一个二元组((x,y))表示代表在此时最喜欢(x)这种玩具,他希望老皮帮他买回(y)个玩具(x),小皮希望知道假如用这(y)个玩具去替换原来的玩具,最多可以产生多长的连续为(x) 的这种玩具的序列?

    输入格式

    第一行一个正整数(N),表示小皮有(N)个玩具
    接来下一行一个由小写字母构成的字符串,表示初始的玩具序列。
    接来下一行一个正整数(q), 表示小皮的(q)种需求
    接下来(q)行,每行输入二元组((x,y)),含义如题目描述所述

    输出格式

    输出一共(q)行,表示每组询问的答案

    样例输入

    5
    aabaa
    2
    a 1
    b 2

    样例输出

    5
    3

    样例解释

    对于第一组询问,我们可以把(b)替换为(a),那么连续为(a)的最长序列长度为5
    对于第二组询问,我们可以把与(b)相邻的两个(a)替换为(b),那么连续为(b)的最长序列长度为3

    数据范围

    对于 10% 的数据:(N,q<=10)
    对于 30% 的数据:(N,q<=100)
    对于另外20%的数据:只存在(a,b)两种字符
    对于100%的数据:(N<=2000,q<=3*10^5,1<=y<=N)
    保证所有出现的字符都是小写字母.

    题解

    对于这道题,可以发现N的范围是可以接受(N^2)的,而q比较大,如果再套个什么东西很容T掉,所以我们选择在外面预处理,dp求出(dp[i][j])表示把原串(i)个字符替换为(j)的最大长度
    实现:(N^2)枚举每个子串,再在外面套一个枚举字母的循环,复杂度(O(26*N^2))
    所以总复杂度(O(26*N^2+q))

    #include<bits/stdc++.h>
    #define Max(a,b) ((a)>(b)?(a):(b))
    #define in(i) (i=read())
    using namespace std;
    inline int read() {
        int ans=0,f=1; char i=getchar();
        while(i<'0' || i>'9') {if(i=='-') f=-1; i=getchar();}
        while(i>='0' && i<='9') {ans=(ans<<1)+(ans<<3)+(i^48); i=getchar();}
        return ans*f;
    }
    int n,m;
    int dp[2010][30];
    char s[2010];
    void init() {
        for(int i=1;i<=26;i++) {
            for(int j=1;j<=n;j++) {
                int tq=0;
                for(int k=j;k<=n;k++) {
                    if((s[k]-'a'+1)!=i) tq++;
                    dp[tq][i]=Max(dp[tq][i],k-j+1);
                }
                for(int k=1;k<=n;k++) if(dp[k-1][i]>dp[k][i]) dp[k][i]=dp[k-1][i];//这里注意一下,因为题目要求替换的数量可能会大于需要替换的字符数量,比如样例中只有一个b,单若是题目要求替换两个a的没有这个更新就会WA
            }
        }
    }
    int main()
    {
        //freopen("toy.in","r",stdin);
        //freopen("toy.out","w",stdout);
        in(n);scanf("%s",s+1);
        init();in(m);
        char t[2];int a;
        for(int i=1;i<=m;i++) {
            scanf("%s%d",t,&a);
            printf("%d
    ",dp[a][t[0]-'a'+1]);
        }
    }
    

    博主蒟蒻,随意转载.但必须附上原文链接

    http://www.cnblogs.com/real-l/

  • 相关阅读:
    要成功先发疯
    情绪ABC理论
    树立和提高威信法
    javaagent
    sonar 使用
    sonar 代码质量管理
    四大思维工具,SWOT、PDCA、DISC、时间管理
    HyperLogLog
    位数组
    git checkout .和git checkout -f的区别;git add . git add -u git add -A的区别
  • 原文地址:https://www.cnblogs.com/real-l/p/9488193.html
Copyright © 2020-2023  润新知