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 ak) and delete it, at that all elements equal to ak + 1 and ak - 1 also must be deleted from the sequence. That step brings ak points to the player.
Alex is a perfectionist, so he decided to get as many points as possible. Help him.
The first line contains integer n (1 ≤ n ≤ 105) that shows how many numbers are in Alex's sequence.
The second line contains n integers a1, a2, ..., an (1 ≤ ai ≤ 105).
Print a single integer — the maximum number of points that Alex can earn.
2
1 2
2
3
1 2 3
4
9
1 2 1 3 2 2 2 2 3
10
Consider the third test example. At first step we need to choose any element equal to 2. After that step our sequence looks like this [2, 2, 2, 2]. Then we do 4 steps, on each step we choose any element equals to 2. In total we earn 10 points.
【题意】给你一个序列,现在要将所有的数删除。如果删除了a[k],则a[k]+1和a[k]-1都将被删除,此次删除的收益为a[k]。求最大收益。
【分析】DP。我们将数字1~maxn依次遍历,dp[i]表示当前数字获得的最大收益,则有两种情况。一:i这个数字在数组中没有,则
dp[i]=i-2<0?0:dp[i-2];二:这个数字在数组中存在,则他可能从i-2的数字那遍历过来,也有可能从i-3的地方遍历过来,继续更新就行了,然后在删除最后一个或者倒数第二个的时候取一下最大值就行了。
#include <bits/stdc++.h> #define pb push_back #define mp make_pair #define vi vector<int> #define inf 0x3f3f3f3f using namespace std; typedef long long LL; const int N = 1e5+50; int n,maxn; int a[N],cnt[N]; LL dp[N]; int main(){ scanf("%d",&n); for(int i=1,x;i<=n;i++){ scanf("%d",&a[i]); maxn=max(maxn,a[i]); cnt[a[i]]++; } LL ans=0; for(int i=1;i<=maxn;++i){ if(!cnt[i]){ dp[i]=i-2<0?0:dp[i-2]; if(i>=maxn-1)ans=max(ans,dp[i]); continue; } dp[i]=1LL*((i-2<0?0:dp[i-2])+1LL*cnt[i]*i); dp[i]=max(dp[i],1LL*((i-3<0?0:dp[i-3])+1LL*cnt[i]*i)); //printf("i:%d dpi:%lld ",i,dp[i]); if(i>=maxn-1)ans=max(ans,dp[i]); } printf("%lld ",ans); return 0; }