cf #634 (Div. 3) E2 - Three Blocks Palindrome (hard version)

思路:
因为每个数比较小,可以从这里切入,开始想的是枚举中间那部分,但是中间固定了2边不好确定,因为2边要一样,所以我们可以固定2边,然后对于中间位置,只需找出出现次数最多的数,前缀和预处理一下。枚举第i个数,前面num个数,然后二分查找后面num个数的位置。

code

#pragma GCC optimize(2)
#include<bits/stdc++.h>
using namespace std;
const int man = 2e5+10;
#define IOS ios::sync_with_stdio(0)
typedef long long ll;
const ll mod = 1e9+7;
int pre[205][man];
int a[man];
	
int main() {
	#ifndef ONLINE_JUDGE
		freopen("in.txt", "r", stdin);
		//freopen("out.txt","w",stdout);
	#endif
	int n;
	int t;
	cin >> t;
	while(t--){
		cin >> n;
		for(int i = 1;i <= n;i++){
			cin >> a[i];
			for(int j = 1;j <= 200;j++){
				pre[j][i] = pre[j][i-1] + (a[i]==j);
			}
		}
		int ans = 0;
		for(int i = 1;i <= n;i++){
			int num = pre[a[i]][i];
			int total = pre[a[i]][n];
			ans = max(ans,total);
			int l = i,r = n;
			int res = -1;
			while(l<=r){
				int mid = (l + r ) >> 1;
				if(total - pre[a[i]][mid] >= num){
					res = mid;
					l = mid + 1;
				}else r = mid - 1;
			}
			//cout << res << endl;
			if(res==-1)continue;
			for(int j = 1;j <= 200;j++){
				ans = max(ans,2 * num + pre[j][res] - pre[j][i]);
			}
		}
		cout << ans << endl;
	}
	return 0;
}

原创文章 93 获赞 12 访问量 8984

猜你喜欢

转载自blog.csdn.net/weixin_43571920/article/details/105546388
今日推荐