E2. Three Blocks Palindrome (hard version) -二分查找 暴力

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,…,ax,b,b,…,by,a,a,…,ax][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;

}

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

秦三码

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值