455A. Boredom

链接:

https://codeforces.com/problemset/problem/455/A

题意

给你一个长度为n的数组,你可以进行多次操作,每次操作选定一个位置,该位置的数ak以及数值上等于ak+1或者ak-1的元素都将删除,然后得分+=ak,求最大得分。
1 ≤ n ≤ 105
1 ≤ ai ≤ 105

Example

input
2
1 2
output
2
input
3
1 2 3
output
4
input
9
1 2 1 3 2 2 2 2 3
output
10

解析

这题原本想用暴力直接找出最大得分,但是数据是1e5,会超时,所以换一种思路:选择一个数字它影响的是它的+1和-1,这个数字可以使用它出现的次数,就比如数字5出现了3次,虽然数字4和数字6在选择数字5的时候被删除,但是数字5自己本身只是被删除了1次,所以可以删除3次数字5,得分就是5 * 3 = 15。
所以可以从小遍历到最大的那个数字,将得分累加到最大的那个数字上,不过每次都需要判断,要么选择这个数字的前一个数字,这个数字得分不计(因为被删除了),要么选择这个数字再前面一个数字,然后再加上这个数字的得分,比较选择二者中最大的那个值。

注意:一定要记得开long long!!!因为最多有1e5个,每个数最大是1e5,所以得分是有可能是1e5*1e5的,会超int范围,因为这个WA一组案例好多遍(—_—)

#include <iostream>
#include <cmath>
#include <algorithm>
#include <string>

using namespace std;

typedef long long ll;

const int N = 1e6 + 10;

ll num[N], n, max_num, ans[N];

int main()
{
	cin >> n;

	while (n--)
	{
		ll x;
		cin >> x;

		num[x]++;//记录每个数字出现的次数,得分就是数字*它的出现次数
		max_num = max(max_num, x);
	}

	//接下来从小到大遍历过去将得分逐步累加至最大数字
	memcpy(ans, num, sizeof num);

	for (int i = 2; i <= max_num; i++)
	{
		ans[i] = max(ans[i - 1], ans[i - 2] + num[i] * i);//计算这个数的得分时,要考虑前面一个选择的数字是不是i - 1
			                                             //如果是i - 1,那这个i就被删除了,那就再前一个的得分加上自己的得分
			                                             //如果不是i - 1,就是再前一个数的得分
	}

	cout << ans[max_num];

	return 0;
}
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值