E2. Three Blocks Palindrome (hard version) (贪心&暴力)
思路:对于数据较大情况,我们考虑要迅速找到区间 [ l , r ] [l,r] [l,r],显然第一个字符串的数字的个数和第三个字符串个数相同 ,要是区间 [ l , r ] [l,r] [l,r]中数的个数越多,我们只需要让 l l l越靠左, r r r越靠右,而 l , r l,r l,r的确定可以通过记录每个数字对于出现的位置(以空间换时间)。遍历第一个字符串的数字个数,最后取 m a x max max即可。
时间复杂度: O ( 200 × n ) O(200\times n) O(200×n)
AC代码:
#include<bits/stdc++.h>
using namespace std;
int main(){
int t,n;
scanf("%d",&t);
while(t--){
scanf("%d",&n);
vector<vector<int> >a(201,vector<int>(n+1));
vector<vector<int> >p(201);//储存每个数的位置.
for(int i=1,x;i<=n;i++)
{
scanf("%d",&x);
for(int j=1;j<=200;j++) //前缀和
a[j][i]=a[j][i-1]+(x==j);
p[x].push_back(i);
}
int ans=0;
for(int k=1;k<=200;k++){ //O(n*200*200)
ans=max(ans,(int)p[k].size());//如果只取一个子串.
for(int i=1;i<=(p[k].size()/2);i++)//左右对称贪心思想.
{
int l=p[k][i-1]+1,r=p[k][p[k].size()-i]-1;//找到区间[l , r]
for(int j=1;j<=200;j++) //取最大值.
{
int x=a[j][r]-a[j][l-1];
ans=max(ans,i*2+x);
}
}
}
printf("%d\n",ans);
}
return 0;
}