题目描述
Alice is a beginner composer and now she is ready to create another masterpiece. And not even the single one but two at the same time!
Alice has a sheet with n notes written on it. She wants to take two such non-empty non-intersecting subsequences that both of them form a melody and sum of their lengths is maximal.
Subsequence is a sequence that can be derived from another sequence by deleting some elements without changing the order of the remaining elements.
Subsequence forms a melody when each two adjacent notes either differs by 1 or are congruent modulo 7.
You should write a program which will calculate maximum sum of lengths of such two non-empty non-intersecting subsequences that both of them form a melody.
题目大意就是从长度为n的序列a[]中,让你取出两个非空不相交子序列,使两个子序列长度最长。
子序列满足相邻数字满足两个性质其中之一
①相差为1
②mod 7的值相同
输入输出格式
The first line contains one integer number n (2 ≤ n ≤ 5000).
The second line contains n integer numbers a1, a2, …, an (1 ≤ ai ≤ 105) — notes written on a sheet.
Print maximum sum of lengths of such two non-empty non-intersecting subsequences that both of them form a melody.
英语渣表示很绝望,看着官方题解搞了好久。
f[x][y]表示两个旋律分别以x和y结束时答案的最大值。如果x==0||y==0证明其中一个子串为空。
只维护x>y的情况,因为若x==y显然不符合题意,若x
<
<script type="math/tex" id="MathJax-Element-19"><</script>y那么由于两个子串并没有顺序可言,相当于f[y][x]。
为了防止交叉,我们更新f[x][y]时,只从f[i][y]
(
i!=y&&i<=x
以上总结一下,说人话大概就是循环为:
for:y=0 to n
for:x=1 to n
if(x==y)continue;
solve();
为了快速更新f数组,需要额外维护两个数组。
maxmod和maxnum数组。
maxmod[j]表示的是f[1~x][y]中a[i]%7==j中f[i][y]最大的值
maxnum同理,表示的是a[i]==j中最大的值。
是不是有一种LIS的感觉?
之后就特别好搞了,分情况转移。
枚举一个新加的数字,如果和之前的数字相比
①mod 7值相同 f[x][y]=max(f[x][y],maxmod[a[x] mod 7]+1)
②大1 f[x][y]=max(f[x][y],maxnum[a[x]-1]+1)
③小1 f[x][y]=max(f[x][y],maxnum[a[x]+1]+1)
④重新找子串 f[x][y]=max(f[x][y],f[0][y]+1)
之后取所有f[x][y]中答案最大值就随便搞搞搞出来了。
#include<bits/stdc++.h>
#define fer(i,j,n) for(int i=j;i<=n;i++)
#define far(i,j,n) for(int i=j;i>=n;i--)
#define ll long long
const int maxn=5010;
const int mxan=1e5+10;
const int INF=1e9+7;
using namespace std;
/*----------------------------------------------------------------------------*/
inline int read()
{
char ls;int x=0,sng=1;
for(;ls<'0'||ls>'9';ls=getchar())if(ls=='-')sng=-1;
for(;ls>='0'&&ls<='9';ls=getchar())x=x*10+ls-'0';
return x*sng;
}
/*----------------------------------------------------------------------------*/
int n;
int a[maxn],f[maxn][maxn],ans=-1;
int maxnum[mxan],maxmod[7];
void init()
{
memset(maxnum,0,sizeof(maxnum));
memset(maxmod,0,sizeof(maxmod));
}
int main()
{
n=read();
fer(i,1,n)a[i]=read();
fer(y,0,n)
{
init();
fer(x,1,n)
{
if(x==y)continue;
if(y>x)
{
maxnum[a[x]]=max(maxnum[a[x]],f[x][y]);
maxmod[a[x]%7]=max(maxmod[a[x]%7],f[x][y]);
continue;
}
f[x][y]=max(f[x][y],maxmod[a[x]%7]+1);
f[x][y]=max(f[x][y],maxnum[a[x]-1]+1);
f[x][y]=max(f[x][y],maxnum[a[x]+1]+1);
f[x][y]=max(f[x][y],f[0][y]+1);
f[y][x]=f[x][y];
maxmod[a[x]%7]=max(maxmod[a[x]%7],f[x][y]);
maxnum[a[x]]=max(maxnum[a[x]],f[x][y]);
ans=max(ans,f[x][y]);
}
}
cout<<ans;
}