【CF455A Boredom】题解


题目链接

题目

Alex doesn't like boredom. That's why whenever he gets bored, he comes up with games. One long winter evening he came up with a game and decided to play it.

Given a sequence $ a $ consisting of $ n $ integers. The player can make several steps. In a single step he can choose an element of the sequence (let's denote it $ a_{k} $ ) and delete it, at that all elements equal to $ a_{k}+1 $ and $ a_{k}-1 $ also must be deleted from the sequence. That step brings $ a_{k} $ points to the player.

Alex is a perfectionist, so he decided to get as many points as possible. Help him.

力克斯不喜欢无聊。

所以每当他感到无聊他就会想出一些游戏。一个冬天的晚上他想出了一个游戏并且决定开始玩这个游戏。

给定一个有n个元素的序列a。你可以做若干次操作。在一次操作中我们可以取出一个数(假设他为x)并删除它,同时删除所有的序列中值为x+1和x-1的数。这一步操作会给玩家加上x分。

输入输出格式

输入格式 第一行一个整数n(1<=n<=10^5),说明这个序列有多少数。 第二行n个整数,分别表示a1,a2……an。

输出格式 一个整数,表示玩家最多能获得多少分

说明: 对于样例4,第一步我们取2,序列变为[2,2,2,2]。接下来每一步都取2,最后获得10分。

思路

先排序离散化,构成一个有序序列 \(b\),每个数出现 \(c_i\) 次。

由于一个数选了,左右都不能选。而再选这个数,对其它数没影响。所以一种数要么全选,要么全不选。

对于第 \(i\) 个数,全选的贡献为 \(b_i\times c_i\)

那我们就可以dp了。每个数有选和不选两种选择,不选直接从前面两种情况选最大值转移。

选和话需要分类讨论。如果前面的书刚好比这个数小1,只能从前面不选的情况转移过来。否则就可以从前面较大值的情况转移过来。

dp是 \(O(n)\) 的,加上排序总复杂度为 \(O(n\log n)\)

Code

#include
using namespace std;
#define int long long
inline int read(){int x=0,f=1;char ch=getchar();
while(ch<'0'||ch>'9'){if(ch=='-')f=-1;
ch=getchar();}while(ch>='0'&&ch<='9'){x=(x<<1)+
(x<<3)+(ch^48);ch=getchar();}return x*f;}
#define N 100010
//#define M
//#define mo
int n, m, i, j, k, T; 
int a[N], b[N], c[N], dp[N][2]; 

signed main()
{
//	freopen("tiaoshi.in","r",stdin);
//	freopen("tiaoshi.out","w",stdout);
	n=read(); 
	for(i=1; i<=n; ++i) b[i]=read(); 
	sort(b+1, b+n+1); 
	for(i=2, a[c[1]=j=1]=b[1]; i<=n; ++i)
	{
		if(b[i]!=a[j]) ++j; 
		a[j]=b[i]; ++c[j]; 
	}
	a[0]=-99999999; 
	for(i=1; i<=j; ++i)
	{
		dp[i][0]=max(dp[i-1][0], dp[i-1][1]); 
		dp[i][1]=a[i]*c[i]+max(dp[i-1][0], (a[i]-a[i-1]!=1 ? dp[i-1][1] : 1ll-1)); 
		// printf("%lld %lld\n", dp[i][0], dp[i][1]); 
	}
	printf("%lld", max(dp[j][0], dp[j][1])); 
	return 0;
}

总结

这是一类挺经典的dp题目。

题目解题关键在于每个数要么全选,要么全不选。剩下的就是dp模板了。

这类题目注意分析性质。同时分析出选与不选可以考虑dp。