E2. Three Blocks Palindrome (hard version)
time limit per test
2 seconds
memory limit per test
256 megabytes
input
standard input
output
standard output
The only difference between easy and hard versions is constraints.
You are given a sequence aa consisting of nn positive integers.
Let's define a three blocks palindrome as the sequence, consisting of at most two distinct elements (let these elements are aa and bb, aa can be equal bb) and is as follows: [a,a,…,ax,b,b,…,by,a,a,…,ax][a,a,…,a⏟x,b,b,…,b⏟y,a,a,…,a⏟x]. There x,yx,y are integers greater than or equal to 00. For example, sequences [][], [2][2], [1,1][1,1], [1,2,1][1,2,1], [1,2,2,1][1,2,2,1] and [1,1,2,1,1][1,1,2,1,1] are three block palindromes but [1,2,3,2,1][1,2,3,2,1], [1,2,1,2,1][1,2,1,2,1] and [1,2][1,2] are not.
Your task is to choose the maximum by length subsequence of aa that is a three blocks palindrome.
You have to answer tt independent test cases.
Recall that the sequence tt is a a subsequence of the sequence ss if tt can be derived from ss 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]s=[1,2,1,3,1,2,1], then possible subsequences are: [1,1,1,1][1,1,1,1], [3][3] and [1,2,1,3,1,2,1][1,2,1,3,1,2,1], but not [3,2,3][3,2,3] and [1,1,1,1,2][1,1,1,1,2].
Input
The first line of the input contains one integer tt (1≤t≤1041≤t≤104) — the number of test cases. Then tt test cases follow.
The first line of the test case contains one integer nn (1≤n≤2⋅1051≤n≤2⋅105) — the length of aa. The second line of the test case contains nn integers a1,a2,…,ana1,a2,…,an (1≤ai≤2001≤ai≤200), where aiai is the ii-th element of aa. Note that the maximum value of aiai can be up to 200200.
It is guaranteed that the sum of nn over all test cases does not exceed 2⋅1052⋅105 (∑n≤2⋅105∑n≤2⋅105).
Output
For each test case, print the answer — the maximum possible length of some subsequence of aa that is a three blocks palindrome.
Example
input
Copy
6 8 1 1 2 2 3 2 1 1 3 1 3 3 4 1 10 10 1 1 26 2 2 1 3 1 1 1
output
Copy
7 2 4 1 1 3
========================================================================
200以内是有其道理的,可以做一个1--200的前缀和,另外贪心的想,我们从头选取的时候,一定是选取当前位置作为 前后段的数字的,当前位置选取之前另一些数字都不是最优的,所以遍历到一个位置就必须把这个位置的数字当成前后段数字,那么前缀和求出来前段数字个数,二分查找后段这个对应数字个数的最右侧,最右侧一定是最优的,然后暴力枚举在此之间1-200的任意一个数字作为b,取最大值即可
# include<bits/stdc++.h>
using namespace std;
# define mod 1000000007
typedef long long int ll;
int sum[200000+10][210],a[200000+10],n;
int main ()
{
int t;
cin>>t;
while(t--)
{
cin>>n;
int ans=0;
for(int i=1;i<=n;i++)
{
cin>>a[i];
for(int j=1;j<=200;j++)
{
sum[i][j]=sum[i+1][j]=0;
// bac[i][j]=bac[i+1][j]=0;
sum[i][j]=sum[i-1][j]+(j==a[i]);
ans=max(ans,sum[i][j]);
}
}
for(int i=1;i<=n;i++)
{
int now=a[i];
int pre=sum[i][now];
int l=i+1,r=n;
while(l<=r)
{
int mid=(l+r)>>1;
if(sum[n][now]-sum[max(0,mid-1)][now]<pre)
r=mid-1;
else
l=mid+1;
}
l=r;
if(l>=i+1)
{
//合法
int nowl=i+1,nowr=l-1;
if(nowr<nowl)
{
ans=max(ans,pre*2);
continue;
}
else
{
for(int j=1;j<=200;j++)
{
ans=max(ans,pre*2+sum[nowr][j]-sum[max(0,nowl-1)][j]);
}
}
}
}
cout<<ans<<endl;
}
return 0;
}