ICode9

精准搜索请尝试: 精确搜索
首页 > 其他分享> 文章详细

CF1692H - Gambling

2022-06-18 13:05:28  阅读:150  来源: 互联网

标签:CF1692H 数字 ++ sum mn 序列 Gambling LL


题目链接:

https://codeforces.com/contest/1692/problem/H

题意:

长为 \(n\) 的序列,从中选择一个连续的子序列,使这个子序列中出现次数最多的数字的数量减去剩余数字的数量最大。

思路:

暴力的方法,枚举每一个区间,然后求该区间中出现次数最多的数字的数量,计算要求计算的最大值,显然超时。
反过来考虑,将所有有相同数字的下标存在一起,假设该数字就是出现次数最多的那个数字,那么求它出现次数减去剩余数字的数量的最大值,其实就是求该序列的最长子段和。
如果出现了,值就是 1,没出现,值就是 -1,对于两个下标之间的数的贡献,都是 -1,设序列为 \(b\),那么 \(b[i] - b[i - 1] - 1\) 就是中间数的数量,也就是前缀和要减去这么多。

代码:

#include <bits/stdc++.h>
using namespace std;
#define LL long long
void solve(){
	LL n;
	cin >> n;
	vector <LL> x(n);
	map <LL, vector <LL> > mp;
	for (int i = 0; i < n; i ++ ){
		cin >> x[i];
		mp[x[i]].push_back(i);
	}
	LL a, l, r, ans = -1e18;
	for (auto [t, b] : mp){
		LL m = b.size(), sum = 0, mn = 1e18, p = 0;
		for (int i = 0; i < m; i ++ ){
			if (i)
				sum -= b[i] - b[i - 1] - 1;
			if (sum < mn){
				mn = sum;
				p = b[i];
			}
			sum ++ ;
			if (sum - mn > ans){
				ans = sum - mn;
				a = t;
				l = p + 1;
				r = b[i] + 1;
			}
		}
	}
	cout << a << " " << l << " " << r << "\n";
}
int main(){
	ios::sync_with_stdio(false);cin.tie(0);
	LL T = 1;
	cin >> T;
	while (T -- )
		solve();
	return 0;
}

标签:CF1692H,数字,++,sum,mn,序列,Gambling,LL
来源: https://www.cnblogs.com/Hamine/p/16387473.html

本站声明: 1. iCode9 技术分享网(下文简称本站)提供的所有内容,仅供技术学习、探讨和分享;
2. 关于本站的所有留言、评论、转载及引用,纯属内容发起人的个人观点,与本站观点和立场无关;
3. 关于本站的所有言论和文字,纯属内容发起人的个人观点,与本站观点和立场无关;
4. 本站文章均是网友提供,不完全保证技术分享内容的完整性、准确性、时效性、风险性和版权归属;如您发现该文章侵犯了您的权益,可联系我们第一时间进行删除;
5. 本站为非盈利性的个人网站,所有内容不会用来进行牟利,也不会利用任何形式的广告来间接获益,纯粹是为了广大技术爱好者提供技术内容和技术思想的分享性交流网站。

专注分享技术,共同学习,共同进步。侵权联系[81616952@qq.com]

Copyright (C)ICode9.com, All Rights Reserved.

ICode9版权所有