codeforces-1335-E Three Blocks Palindrome
传送门:
easy:https://codeforces.com/contest/1335/problem/E1
hard:https://codeforces.com/contest/1335/problem/E2
题意:
定义 three blocks palindrome 为 aaaaabbbaaaaa,其中两边的a必须个数相等 而且序列中只存在两种元素
1 1 1 2 3 2 1 1 1 是不可以的 1 1 1 2 1 2 1 1 1 也是不可以的
给你一段序列 找到最长的 three blocks palindrome 子序列(可以不连续)
这个题 是个纯暴力
说一下思路
用一个前缀和 sum[i][j] 记下来在 i 这个位置有多少 j 1<=i<=n<=2e5 1<= j = a[i]<=200
把a[i]出现过的位置记下来,后面有用,我是用的vector
然后遍历1-200 内的每一个数作为上面的a,也就是在两边的部分 更新最大值
找到了 a ,在每两个 a 之间找到(这两个a中间夹着的重复的数的最大值+min(1到左面的a的位置有多少a,右面的a的位置到结尾有多少a )*2 )的最大值
不理解??
5 5 5 5 5 5 5 1 1 2 3 2 1 1 1 a=1时最优的选择是什么呢 1 1 2 2 1 1 因为要保证两边a的距离相等所以取小 因为a=1指定没有a=5长,所以每次取最大
这个在每两个a之间找,暴力的话可以套俩循环,easy是指定能过的,hard没有试,要做一下优化
想一下 1 2 3 4 5 6 7 8 这些个位置,如果是找1 8 max(之间中间夹着的重复的数)一定比1 5之间的 max(之间中间夹着的重复的数) 要多,如果右面是位置5的情况比较大,那一定是1往右移了
所以我们duck不必套俩循环,一左一右往中间缩就好了
行了,去模拟吧
还有 sum 不用memset 初始化会tle 他是每次覆盖上去的
j<ve[i].size()/2 不能写成j*2<ve[i].size() j=1,ve[i].size()=3会错
maxx初值赋成1 因为最小的长度就是它本身也是1,而且这种情况根本无法更新最大值,赋成-1或者0你就凉了
easy版代码就不粘了,比这个还要暴力呢
#include<bits/stdc++.h> using namespace std; #define ll long long const int mod=1e9+7; const int inf=0x3f3f3f3f; int a[200009]; int sum[200009][209];//i j 在i处有多少j vector<int>ve[300]; int main() { int _; for(scanf("%d",&_); _; _--) { for(int i=0; i<202; i++) ve[i].clear(); int n; scanf("%d",&n); for(int i=1; i<=n; i++) { scanf("%d",&a[i]); ve[a[i]].push_back(i); for(int j=1; j<=200; j++) { if(j==a[i]) sum[i][j]=sum[i-1][j]+1; else sum[i][j]=sum[i-1][j]; } } int maxx=1; for(int i=1; i<=200; i++) { for(int j=0; j<ve[i].size()/2; j++) { int mx=0; int k=ve[i].size()-j-1; for(int k_=1; k_<=200; k_++) { int sm=sum[ve[i][k]-1][k_]-sum[ve[i][j]][k_]; mx=max(mx,sm); } maxx=max(mx+2*(j+1),maxx); } } printf("%d\n",maxx); } return 0; }