D. Two Melodies
time limit per test2 seconds
memory limit per test256 megabytes
inputstandard input
outputstandard output
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.
Input
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.
Output
Print maximum sum of lengths of such two non-empty non-intersecting subsequences that both of them form a melody.
Examples
input
4
1 2 4 5
output
4
input
6
62 22 60 61 48 49
output
5
Note
In the first example subsequences [1, 2] and [4, 5] give length 4 in total.
In the second example subsequences [62, 48, 49] and [60, 61] give length 5 in total. If you choose subsequence [62, 61] in the first place then the second melody will have maximum length 2, that gives the result of 4, which is not maximal.
题目大意
有一个长度为
N(2≤N≤5000)
的序列,要求从中选择两个相互独立的子序列,每个子序列相邻元素之间差
1
或对于
解题思路
首先很容易相当
dp[i][j]
表示两个字序列分别以
i,j
结尾的最长长度。转移就是枚举下一个位置,总时间复杂度为
O(N3)
,显然无法通过。
考虑固定一个
i
,则对每个
AC代码
#include <iostream>
#include <algorithm>
#include <cstdio>
#include <cstring>
#include <vector>
#include <queue>
#include <stack>
#include <cstdlib>
#include <cmath>
#include <map>
using namespace std;
#define mem(a,b) memset((a),(b),sizeof(a))
const int MAXN=5000+3;
const int MAXA=100000+3;
int N, a[MAXN];
int dp[MAXN][MAXN];//表示一个序列以i结尾,一个序列以j结尾的最大长度
int max_mod[10], max_a[MAXA];//表示此时a[j]%7为各个值的最长序列,表示a[j]为各个值的最长序列
int main()
{
scanf("%d", &N);
for(int i=1;i<=N;++i)
scanf("%d", &a[i]);
int ans=0;
for(int i=0;i<=N;++i)
{
for(int j=0;j<7;++j)
max_mod[j]=0;
for(int j=1;j<=N;++j)
max_a[a[j]]=0;
for(int j=1;j<i;++j)//预处理出此时各个情况的最大长度
{
max_mod[a[j]%7]=max(max_mod[a[j]%7], dp[i][j]);
max_a[a[j]]=max(max_a[a[j]], dp[i][j]);
}
for(int j=i+1;j<=N;++j)//进行转移并更新维护的值
{
dp[i][j]=max(max(max_a[a[j]-1], max_a[a[j]+1]), max(max_mod[a[j]%7], dp[i][0]))+1;
dp[j][i]=dp[i][j];
max_mod[a[j]%7]=max(max_mod[a[j]%7], dp[i][j]);
max_a[a[j]]=max(max_a[a[j]], dp[i][j]);
ans=max(ans, dp[i][j]);
}
}
printf("%d\n", ans);
return 0;
}