codeforce 20140808 C. Boredom

C. Boredom
time limit per test
1 second
memory limit per test
256 megabytes
input
standard input
output
standard output

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.

Input

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 a1a2, ..., an (1 ≤ ai ≤ 105).

Output

Print a single integer — the maximum number of points that Alex can earn.

Sample test(s)
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
Note

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.

题意就是 从一个序列中删除一个数K  同时删除K-1,K+1  此时能够得到K分不 求最后能得到的最多的分数

主要的是一个dp的思路  就是首先 读取序列的时候保存出现过的数字的个数p[i]  删除它能得到的分数就是p[i]*i

因为同时删除相邻的两个数 所以就从小的数开始算起  dp[0]=0  dp[1]=p[1]

计算到i时的分数 如果是删除了i-1 则dp[i]=dp[i-1]  如果是删除了i-2  则dp[i]=dp[i-2]+p[i]*i;

取大值就可以了

代码如下。。。dp还是硬伤

#include <cstdio>
#include <iostream>
#include <cstring>
#include <cmath>
#include <algorithm>
#include <string.h>
#include <string>

#define eps 1e-8
#define op operator
#define MOD  10009
#define MAXN  100010

#define FOR(i,a,b)  for(int i=a;i<=b;i++)
#define FOV(i,a,b)  for(int i=a;i>=b;i--)
#define REP(i,a,b)  for(int i=a;i<b;i++)
#define REV(i,a,b)  for(int i=a-1;i>=b;i--)
#define MEM(a,x)    memset(a,x,sizeof a)
#define ll __int64

using namespace std;

struct node
{
    int num;
    int cnt;
    int sum;
    bool operator<(const node& x)const
    {
        return sum>x.sum;
    }
};

node no[MAXN];

int a[MAXN];
int b[MAXN];
int main()
{
//freopen("ceshi.txt","r",stdin);
    int n;
    while(scanf("%d",&n)!=EOF)
    {
        MEM(b,0);
        int temp;
        for(int i=0;i<MAXN;i++)
            no[i].cnt=0;
        int c=0;
        for(int i=0;i<n;i++)
        {
            scanf("%d",&temp);
            no[temp].num=temp;
            no[temp].cnt++;
            if(no[temp].cnt==1) c++;
        }
        for(int i=1;i<MAXN;i++)
        {
            no[i].sum=no[i].cnt*i-no[i-1].cnt*(i-1)-no[i+1].cnt*(i+1);
        }
        sort(no,no+MAXN);
        ll s=0;
        for(int i=0;i<MAXN;i++)
        {
            if(no[i].sum>0)
            {
                s+=no[i].num*no[i].cnt;
            }
            no[no[i].num-2].sum+=(no[no[i].num-1].num*no[no[i].num-1].cnt);
        }
        printf("%I64d\n",s);
//        for(int i=0;i<n;i++)
//            cout<<no[i].num<<endl;
    }
    return 0;
}


评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值