题解:我们定义左边子序列的前缀数组为l[i][k]表示在i-1位置k出现的个数。后缀数组r[i][k]表示i+1位置到n位置出现k的次数。这样我们只需要把这两个比较取个min再*2就能得到两边序列的长度。之后枚举i到j区间内出现1~26的次数最多的个数(用m表示),最后的结果就是m+2*min(l[i][k],r[j][k])。复杂度的话,因为我们要枚举i和j的端点和数字出现的次数,所以总共是O(26*n^2)。反正这题是弱化数据版,写写就能过。
代码:
#include <cstdio>
#include <iostream>
#include <cstring>
#include <string>
#include <algorithm>
using namespace std;
const int N=2010;
int l[N][210];
int r[N][210];
int cnt[N];
int a[N];
int main()
{
int t;
cin>>t;
while(t--)
{
memset(l,0,sizeof l);
memset(r,0,sizeof r);
memset(cnt,0,sizeof cnt);
int n;
cin>>n;
for(int i=1;i<=n;i++)
{
cin>>a[i];
for(int j=1;j<=26;j++)
{
l[i][j]=cnt[j];
}
cnt[a[i]]++;
}
memset(cnt,0,sizeof cnt);
for(int i=n;i>=1;i--)
{
for(int j=1;j<=26;j++)
{
r[i][j]=cnt[j];
}
cnt[a[i]]++;
}
int maxx=-1;
for(int i=1;i<=n;i++)
{
int m=0;
for(int j=1;j<=n;j--)
{
if(a[j]==a[i]) m++;
for(int k=1;k<=26;k++)
{
maxx=max(maxx,m+min(l[i][k],r[j][k])*2);
}
}
}
cout<<maxx<<endl;
}
return 0;
}