G - Stonks Editorial
by
potato167
以下の条件を満たす数列 \(A\) を考えます。
- \(A_{i} \in \{-1, 0, 1\}\)
- \(\forall i = 1, 2, \dots , N : \sum_{k = 1}^{i}A_{i}\leq 0\)
以下の値の最大値を求められれば良いです。
\[\sum_{i = 1}^{N}A_{i}P_{i}\]
\(A_{i}\) の全てに \(1\) を足します。すると答えは \(\sum P\) だけ増えます。このとき、 \(A\) は以下の条件を全て満たします。
- \(A_{i} \in \{ 0, 1, 2\}\)
- \(\forall i = 1, 2, \dots , N : \sum_{k = 1}^{i}A_{i}\leq i\)
- \(\sum A_{i} = N\)
これらを満たす \(A\) は全て以下の方法で構築することができます。
- 初め \(A_{i} = 2\) で初期化する
- \(i = 1, 2, ..., N\) の順に、以下の操作をする
- \(j \leq i\) かつ \(A_{j} \neq 0\) を満たす \(j\) をひとつ選び、\(A_{j} -= 1\) をする。
ここで、\(j\) を選ぶ際にわざわざ \(P_{j}\) が大きいもの選んでも何の価値にもなりません。
よって、この \(j\) を選ぶ際、\(P_{j}\) が最小のものを選ぶという貪欲が正しいです。
この貪欲は priority queue を用いて簡単に実装することができます。
#include<bits/stdc++.h>
using namespace std;
using ll = long long;
int main(){
int N;
cin >> N;
ll ans = 0;
priority_queue<ll> pq;
while(N--){
ll a;
cin >> a;
ans += a;
pq.push(-a), pq.push(-a);
ans += pq.top();
pq.pop();
}
cout << ans << "\n";
}
posted:
last update: