CF1335E2 Three Blocks Palindrome (hard version)

这道题的easy版本我写的是n^2*26的,对于这题显然不够用。

我们发现上一题我们遍历了很多重复的情况,因为我们是按位置进行遍历的,所以要全部遍历,这次我们优化一下

我们发现个数最多只有200,因此我们按这个作为枚举对象。进一步发现,因为我们枚举的是a这些数作为两边

那么对于每个数,只需要找到他在哪些地方出现过,就能作为枚举的边界

因此存一个vector来代表他的出现位置,之后中间这段同样枚举200次,这样复杂度就比较优秀了

#include<bits/stdc++.h>
using namespace std;
typedef long long ll;
const int N=2e5+10;
const int mod=1e9+7;
int s[N][210];
int a[N];
vector<int> num[210];
int main(){
    int t;
    cin>>t;
    while(t--){
        int n;
        for(int i=0;i<210;i++)
            num[i].clear();
        cin>>n;
        int i,j;
        for(i=1;i<=n;i++){
            cin>>a[i];
            num[a[i]].push_back(i);
            for(j=1;j<=200;j++)
                s[i][j]=s[i-1][j];
            s[i][a[i]]++;
        }
        int l,r;
        int ans=0;
        for(i=1;i<=200;i++)
            ans=max(ans,s[n][i]);
        for(i=1;i<=200;i++){
            int cnt1=0;
            int si=(int)num[i].size();
            if(si==1)
            continue;
            for(j=0;j<si/2;j++){
                int l=num[i][j];
                int r=num[i][si-j-1];
                cnt1=(j+1)*2;
                for(int k=1;k<=200;k++){
                    ans=max(ans,cnt1+s[r-1][k]-s[l][k]);
                }
            }
        }
        cout<<ans<<endl;
    }
}
View Code

 

posted @ 2020-04-26 11:07  朝暮不思  阅读(136)  评论(0编辑  收藏  举报