アドレス:http : //codeforces.com/problemset/problem/455/A
アレックスは退屈が好きではありません。それが彼が退屈するときはいつでもゲームを思いつく理由です。ある長い冬の夜、彼はゲームを考え出し、それをプレイすることにしました。
n個の 整数で 構成される シーケンスを指定 します。プレイヤーはいくつかのステップを踏むことができます。単一のステップで、シーケンスの要素を選択し(これをa kとしましょう)、削除できます。その 場合、k + 1および a k -1に等しいすべての要素 もシーケンスから削除する必要があります。そのステップはもたらし k個の プレイヤーにポイントを。
アレックスは完璧主義者なので、できるだけ多くのポイントを獲得することにしました。彼を助けて。
入力
最初の行は、整数含ま N (1≤ N ≤10 5を示しどのように多くの数は、アレックスのシーケンスであることを)。
2行目は含ま N 、整数 1、 2、...、 N (1≤ I ≤10 5)。
出力
単一の整数を出力します— Alexが獲得できる最大ポイント数。
例
2
1 2
2
3
1 2 3
4
9
1 2 1 3 2 2 2 2 3
10
注意
3番目のテスト例を考えます。最初のステップでは、2に等しい要素を選択する必要があります 。そのステップの後、シーケンスは次のようになります[ 2、2、2、2 ]。次に 、4つのステップを実行し、各ステップで2に等しい要素を選択します 。合計で10ポイントを獲得し ます。
トピックの意味:akを削除すると、この配列のすべてのak + 1とak-1が削除され、同時にakポイントを取得します。あなたが得ることができる最大のスコアを見つけます。
解析:各数値はバケットソートされた数値です。このようにして、以下の1より大きい差の影響はありません。。右から0の位置から、数値iを削除するために、i-1が削除された場合、iは当然存在しません。この時点では、dp [i] = dp [i-1]、スコアは変化しません。削除する必要がありました。i-1が削除されない場合、dp [i] = dp [i-2] + num [i] * i;
#include <iostream> #include <cstring> #include <cstdio> #include <algorithm> using namespace std; typedef long long ll; const int maxn = 1e5 + 10 ; ll num [maxn]; ll dp [maxn]; int main() { ll n; cin >> n; int maxx = -1 ; int x; for(int i = 1 ; i <= n; i ++ ) { cin>> x; num [x] ++ ; if(maxx < x) maxx = x; } dp [ 1 ] = num [ 1 ]; // 初始dp [1] for(int i = 1 ; i <= maxx; i ++ ) { dp [i] = max(dp [i- 1 ]、dp [i- 2 ] + num [i] * i) ; } cout << dp [maxx] << endl; }