suxxsfe

一言(ヒトコト)

CF1335E Three Blocks Palindrome

就是我这个菜鸡,赛时写出了 E2 的做法,但是算错复杂度,导致以为自己的做法只能AC E1,就没交到 E2 上,然后赛后秒A.....

题意

定义一种字串为形如:\([\underbrace{a, a, \dots, a}_{x}, \underbrace{b, b, \dots, b}_{y}, \underbrace{a, a, \dots, a}_{x}]\)

问你在给定的字串中,符合这种要求的最大子序列(可以不连续)的长度
给出数列长度 \(n\le 2\cdot 10^5\),数列中每个数 \(a_i\le 200\)


考虑暴力枚举 \(a\),然后对于每一个 \(a\),枚举 \(x\),也就是两边的 \(a\) 的 个数
用两个 vector,分别记录从前和从后数,第 \(x\)\(a\) 的位置
然后一直枚举到第 \(\lfloor\dfrac{\text{a出现的次数}}{2}\rfloor\)
此时,再暴力枚举 \(b\),记录一个前缀和 \(sum_{b,i}\),表示 \(b\) 这个数,在前 \(i\) 位中出现的次数
假设在 vector 中记录的整数第 \(x\)\(a\) 的位置是 \(pos1\),倒数第 \(x\) 个位置是 \(pos2\),那么中间 \(b\) 的个数就是 \(sum_{b,pos2}-sum_{b,pos1-1}\)
然后给所有枚举到的 \(b\) 取一个 \(\max\) 就行

注意在 \(pos1,pos2\) 中,要分别先 push_back 一个 \(0\)\(n+1\),意思是正数倒数第 \(0\) 第出现的位置,同时方便后面的枚举

每枚举一个 \(a\),设它出现的次数为 \(num_a\),则它的复杂度为 \(200\times num_a\)
那么总复杂度是 \(\sum_{i=1}^{200}num_a\times 200=200\times n\)

赛时没想到这点导致并没有交 E2 qaq

#include<cstdio>
#include<algorithm>
#include<iostream>
#include<cmath>
#include<map>
#include<iomanip>
#include<vector>
#include<cstring>
#define reg register
#define EN std::puts("")
#define LL long long
inline int read(){
	register int x=0;register int y=1;
	register char c=std::getchar();
	while(c<'0'||c>'9'){if(c=='-') y=0;c=std::getchar();}
	while(c>='0'&&c<='9'){x=x*10+(c^48);c=std::getchar();}
	return y?x:-x;
}
int sum[206][200006];
std::vector<int>pos1[206],pos2[206];
int num[206];
int a[200006];
int main(){int T=read();while(T--){
//		std::printf("%lld",sizeof sum+sizeof pos1+sizeof pos2+sizeof a);
	int n=read();
	for(reg int i=1;i<=200;i++){
		pos1[i].clear();pos2[i].clear();
		pos1[i].push_back(0);pos2[i].push_back(n+1);
	}
	for(reg int x,i=1;i<=n;i++){
		for(x=1;x<=200;x++) sum[x][i]=sum[x][i-1];
		a[i]=read();sum[a[i]][i]++;
		num[a[i]]++;pos1[a[i]].push_back(i);
	}
	for(reg int i=n;i;i--) pos2[a[i]].push_back(i);
	reg int ans=0;
	for(reg int a=1;a<=200;a++){
		for(reg int x=0;x<=num[a]>>1;x++){
			for(reg int b=1;b<=200;b++)
				ans=std::max(ans,(x<<1)+sum[b][pos2[a][x]-1]-sum[b][pos1[a][x]]);
		}
	}
	std::printf("%d\n",ans);
	std::memset(num,0,sizeof num);
	for(reg int x,i=1;i<=n;i++){
		for(x=1;x<=200;x++) sum[x][i]=0;
	}
}
	return 0;
}
posted @ 2020-04-14 11:52  suxxsfe  阅读(127)  评论(0编辑  收藏  举报