Codeforces 813D Two Melodies 题解

博客主要介绍了Codeforces 813D题目的解题思路,内容涉及动态规划和模运算优化。题目要求找到原序列中两个无重复部分的Melody子序列,使得它们的长度之和最大。博主分享了如何通过dp数组和优化技巧解决此问题,包括将数对模7进行处理以降低复杂度。
部署运行你感兴趣的模型镜像

原链接
洛谷
Codeforces

题意简述

给定一个 n ( n < = 5000 ) n(n<=5000) n(n<=5000),以及 n n n个数 a 1 , a 2 , a 3 , ⋯   , a n ( a i < = 1 e 5 ) a_1,a_2,a_3,\cdots,a_n(a_i<=1e5) a1,a2,a3,,an(ai<=1e5)定义一个 M e l o d y Melody Melody子序列(和"最长上升子序列"中的"子序列"定义一样,是指在原序列中相对顺序不变但是不一定连续的一段子序列)如下:

对于任意相邻的两个元素,一定满足这两个元素差为1或者两个元素除7同余。

请在原序列中找出两个无重复部分的 M e l o d y Melody Melody子序列并且选出的两个长度加起来最大。

(偷偷开心一下:这个盗的是洛谷上的翻译,它是我提供的)

数据

输入

第一行一个正整数 n n n
接下来一行有 n n n个正整数,顺序给出 a 1 , a 2 ⋯ a n a_1,a_2\cdots a_n a1,a2an

输出

如题。最长的两段不重复 M e l o d y Melody Melody序列的长度和。

样例

输入
4
1 2 4 5
输出
4

输入
6
62 22 60 61 48 49
输出
5

解释

解释:样例2中选出 62 , 48 , 49 62,48,49 62,48,49 60 , 61 60,61 60,61这两个 M e l o d y Melody Melody子序列能使得总长度最大 = 5 ( 即2+3 ) =5(\text{即2+3}) =5(2+3)

思路

很久以前,看到这个题,只看懂了题意,不会做。但是为了搞社区贡献就交了翻译,过了(事实证明没什么用)。

现在终于会做了,写篇题解纪念一下。。。

显然是个 d p dp dp吧。。。我们有一个朴素的 d p dp dp方程, d p [ i ] [ j ] dp[i][j] dp[i][j]表示第一段到 i i i,第二段到 j j j的最大长度和。显然,我们要找一个最大的 k k k满足 a [ k ] = a [ j ] ± 1 a[k]=a[j]\pm1 a[k]=a[j]±1 a [ k ] ≡ a [ j ] ( m o d 7 ) a[k]≡a[j]\pmod 7 a[k]a[j](mod7)。此时用 d p [ i ] [ k ] + 1 dp[i][k]+1 dp[i][k]+1更新 d p [ i ] [ j ] dp[i][j] dp[i][j] d p [ i ] [ j ] dp[i][j] dp[i][j]初始值设为 d p [ i ] [ 0 ] + 1 dp[i][0]+1 dp[i][0]+1

但是显然这个转移是 O ( n 3 ) O(n^3) O(n3)d的,过不去。所以我们想想如何优化。此时注意到 a i < = 1 e 5 a_i<=1e5 ai<=1e5,这告诉我们我们珂以把 a i a_i ai作为数组下标。设 m a x m [ x ] maxm[x] maxm[x]表示满足 a [ k ] ≡ x ( m o d 7 ) a[k]≡x \pmod 7 a[k]x(mod7) k k k d p [ i ] [ k ] dp[i][k] dp[i][k]最大的,注意 x ∈ [ 0 , 7 ) x\in[0,7) x[0,7) m a x n [ x ] maxn[x] maxn[x]表示满足 a [ k ] = x a[k]=x a[k]=x k k k d p [ i ] [ k ] dp[i][k] dp[i][k]最大的。当然,我们每次枚举 i i i的时候,都要计算一下这个 m a x m maxm maxm m a x n maxn maxn。除此之外,我们在一边计算 d p [ i ] [ j ] dp[i][j] dp[i][j]的时候也要记得一边更新 m a x m maxm maxm m a x n maxn maxn

(Q:为什么叫 m a x m maxm maxm m a x n maxn maxn?)
(A: m m m结尾表示 m o d u l o modulo modulo,即模运算。 n n n结尾表示 n u m b e r number number,即数值。洛谷上的M_sea巨佬称其为 m a x m o d maxmod maxmod m a x n u m maxnum maxnum。)

代码:

#include<bits/stdc++.h>
using namespace std;
namespace Flandle_Scarlet
{
    #define N 5010
    #define Val 100100
    int n,a[N];
    void Input()
    {
        scanf("%d",&n);
        for(int i=1;i<=n;++i)
        {
            scanf("%d",&a[i]);
        }
    }

    int dp[N][N];
    int maxm[7],maxn[Val];
    bool check(int a,int b) // 判断 a 和 b 是否能在原序列中相邻
    {
        if ((a-b)%7==0) return 1;
        if (abs(a-b)==1) return 1;
        return 0;
    }
    int max4(int a,int b,int c,int d)//四个取最值
    {
        return max(max(a,b),max(c,d));
    }
    int up(int &x,int y)//用y更新x的最大值
    {
        x=max(x,y);
    }
    void DP()
    {
        int ans=-1;
        memset(dp,0,sizeof(dp));
        for(int i=0;i<=n;++i)
        {
            memset(maxn,0,sizeof(maxn));
            memset(maxm,0,sizeof(maxm));
            for(int j=1;j<=i;++j)
            {
                up(maxm[a[j]%7],dp[i][j]);
                up(maxn[a[j]],dp[i][j]);
            }// 转移方程
            for(int j=i+1;j<=n;++j)
            {
                dp[i][j]=max4(dp[i][0],maxm[a[j]%7],maxn[a[j]-1],maxn[a[j]+1])+1;
                // 讨论四种情况取最大值
                up(maxm[a[j]%7],dp[i][j]);
                up(maxn[a[j]],dp[i][j]);//记得更新maxm个maxn
                up(ans,dp[i][j]);//更新答案
                dp[j][i]=dp[i][j];///对称的,所以答案一样(这个上面忘了说了,不写就WA声一片了)
            }
        }
        printf("%d\n",ans);
    }

    void Main()
    {
        Input();
        DP();
    }
};
main()
{
    Flandle_Scarlet::Main();
    return 0;
}

您可能感兴趣的与本文相关的镜像

ACE-Step

ACE-Step

音乐合成
ACE-Step

ACE-Step是由中国团队阶跃星辰(StepFun)与ACE Studio联手打造的开源音乐生成模型。 它拥有3.5B参数量,支持快速高质量生成、强可控性和易于拓展的特点。 最厉害的是,它可以生成多种语言的歌曲,包括但不限于中文、英文、日文等19种语言

评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
红包 添加红包
表情包 插入表情
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值