题目链接

https://ac.nowcoder.com/acm/contest/9667/J

解题思路

一开始还以为选奇数或偶数权值最大的就行嘞,结果发现是错的,比如1,4,可以两个都选,并不是只能选奇数或者偶数。
简单dp;
dp[i][1/0]表示第i个数选还是不选;但是这里的第i个数并不是a数组的下标i。
首先,输入的时候统计每个数的个数;
我们再对整个数组从小到大排序,进行类离散化处理,比如8,1,1,6,7,6,1,8,处理之后为1,6,7,8,dp的下标i=1对应的1,i=2对应6……;
转移方程:
若第i个比第i-1个大1,此时i和i-1只能选一个,所以转移方程为dp[i][0]=max(dp[i-1][0],dp[i-1][1]),dp[i][1]=dp[i-1][0]+(ll)a[i]*cnt[a[i]]
否则,dp[i][0]=max(dp[i-1][0],dp[i-1][1]),dp[i][1]=dp[i][0]+(ll)a[i]*cnt[a[i]];

AC代码

#include<bits/stdc++.h>
#define ll long long
using namespace std;
const int N=2e5+10;

ll ans,dp[N][2];
int n,a[N],cnt[N];

int main()
{
    cin>>n;
    for(int i=1;i<=n;i++) cin>>a[i],cnt[a[i]]++;
    sort(a+1,a+n+1);
    n=unique(a+1,a+n+1)-a-1;//类离散化
    for(int i=1;i<=n;i++)
    {
        if(a[i]==a[i-1]+1)
        dp[i][0]=max(dp[i-1][0],dp[i-1][1]),
        dp[i][1]=dp[i-1][0]+(ll)a[i]*cnt[a[i]];//勿忘乘个数
        else 
        dp[i][0]=max(dp[i-1][0],dp[i-1][1]),
        dp[i][1]=dp[i][0]+(ll)a[i]*cnt[a[i]];//勿忘乘个数
        ans=max(ans,max(dp[i][0],dp[i][1]));
    }
    cout<<ans<<endl;
}