题意:
给定一个长度为 nnn 的数列定义,这个回文子数列可以是数字完全相同的一个子数列,也可以是只包含两种数字,且其中一种平均分布在另一种数字的两侧。求出最长的回文子数列长度
因为 aaa 不大所以直接枚举 aaa 这样两边的数就可以确定,中间的区间也可以确定,然后再从中间的区间枚举 bbb ,这样选取最大值。
const int N = 3e5 + 10, M = 200;
int n, a[N];
int vis[N], cnt[N][220], pos[N], far[N], last[N], pre[N];
int st[N], f[N];
int ans;
int main()
{
int t;
sd(t);
while (t--)
{
ans = 1;
sd(n);
rep(i, 1, n)
sd(a[i]);
rep(i, 2, M)
pos[i] = cnt[0][i] = 0;
rep(i, 1, n)
{
rep(j, 1, M)
cnt[i][j] = cnt[i - 1][j];
cnt[i][a[i]]++;
}
rep(i, 1, n)
pre[i] = pos[a[i]],
pos[a[i]] = i;
rep(i, 1, M)
pos[i] = far[i] = 0;
per(i, n, 1) if (!pos[a[i]]) far[a[i]] = i, pos[a[i]] = i;
rep(i, 1, M)
vis[i] = 0;
rep(i, 1, n)
{
if (!vis[a[i]])
f[i] = far[a[i]], st[i] = 1, vis[a[i]] = 1;
else
f[i] = pre[f[last[a[i]]]], st[i] = st[last[a[i]]] + 1;
last[a[i]] = i;
if (i < f[i])
{
int l = i + 1, r = f[i] - 1, ma = 0;
rep(j, 1, M) ma = max(ma, cnt[r][j] - cnt[l - 1][j]);
ans = max(ans, (st[i] << 1) + ma);
}
}
pd(ans);
}
return 0;
}