E

The only difference between easy and hard versions is constraints.

You are given a sequence a consisting of n positive integers.

Let's define a three blocks palindrome as the sequence, consisting of at most two distinct elements (let these elements are a and b, a can be equal b) and is as follows: [a,a,…,a������������x,b,b,…,b����������y,a,a,…,a������������x]. There x,y are integers greater than or equal to 0. For example, sequences [], [2], [1,1], [1,2,1], [1,2,2,1] and [1,1,2,1,1] are three block palindromes but [1,2,3,2,1], [1,2,1,2,1] and [1,2] are not.

Your task is to choose the maximum by length subsequence of a that is a three blocks palindrome.

You have to answer t independent test cases.

Recall that the sequence t is a a subsequence of the sequence s if t can be derived from s by removing zero or more elements without changing the order of the remaining elements. For example, if s=[1,2,1,3,1,2,1], then possible subsequences are: [1,1,1,1], [3] and [1,2,1,3,1,2,1], but not [3,2,3] and [1,1,1,1,2].
View Code

题意杀我,一定要明白是找到aaabbbaaa这样的回文串,不是普通的回文串,而且子序列的相对位置不可以变,可是明白了题意之后我满脑子都是2^n的算法,显然是不现实的。借用sc学长的题解做法:我们使用三重循环:第一重枚举a是什么,第二重枚举取多少个a,第三种枚举b取什么。这样的话,我们知道,取同样多的a,中间的区间越大,b的个数可能就越多,所以我们取前x个a和后x个a,在这中间找b,由此就有了一个优化:我们记录每一个数出现的所有位置,也记录每一个数在每一个位置出现的前缀和。

 1 #include<algorithm>
 2 #include<iostream>
 3 #include<cstring>
 4 #include<cstdio>
 5 #include<vector>
 6 using namespace std;
 7 const int maxn=2e3+5;
 8 int t;
 9 int n;
10 int a[maxn];
11 int ans;
12 int s[maxn][30];
13 vector<int>v[30];
14 int main()
15 {
16     scanf("%d",&t);
17     while(t--)
18     {
19         scanf("%d",&n);
20         memset(s,0,sizeof(s));
21         ans=0;
22         for(int i=0;i<30;++i)v[i].clear();
23         for(int i=1;i<=n;++i)
24         {
25             scanf("%d",&a[i]),v[a[i]].push_back(i);
26             for(int j=1;j<=26;++j)
27                 s[i][j]=s[i-1][j];
28             s[i][a[i]]++;//前缀和 
29         }
30         for(int i=1;i<=26;++i)
31         {
32             ans=max(ans,s[n][i]);
33             int hal=(s[n][i]>>1);
34             for(int j=1;j<=hal;++j)//枚举取多少个a 
35             {
36                 int l=v[i][j-1]+1,r=v[i][s[n][i]-j]-1;
37                 if(r>=l)
38                 {
39                     for(int k=1;k<=26;++k)
40                     {
41                         ans=max(ans,2*j+s[r][k]-s[l-1][k]);
42                     }
43                 }
44             }
45         }
46         cout<<ans<<endl;
47     }
48     return 0;
49 }
原文地址:https://www.cnblogs.com/yuelian/p/12738614.html