ferinの競プロ帳

競プロについてのメモ

ARC069 E - Frequency

問題ページ
E: Frequency - AtCoder Regular Contest 069 | AtCoder

解法

辞書順最小なのでその時点で追加できる最小のものを追加していくようにする。

0 1 2 3 4 5 6 7 8 9
1 2 1 3 2 4 2 5 8 1 -> 8が3(=(8-5)*(8以上の数の個数))回追加 (最大の石の数は8)
1 2 1 3 2 4 2 5 5 1 -> 7が2(=(5-4)*(5以上の数の個数))回追加 (最大の石の数は5)
1 2 1 3 2 4 2 4 4 1 -> 5が3回追加 (最大の石の数は4)
1 2 1 3 2 3 2 3 3 1 -> 3が4回追加 (最大の石の数は3)
1 2 1 2 2 2 2 2 2 1 -> 1が7回追加 (最大の石の数は2)
1 1 1 1 1 1 1 1 1 1 -> 0が10回追加(最大の石の数は1)
0 0 0 0 0 0 0 0 0 0

a[i]が取りうる値を昇順に並べたものをX_iとする。X_i以上で最も左に存在するindexが(X_i以上のa[i]の個数)*(X_i-X_{i-1})回追加される。したがってX_i以上の個数とX_i以上で最も左にあるindexを保持しておけば計算できる。

//#define __USE_MINGW_ANSI_STDIO 0
#include <bits/stdc++.h>

using namespace std;
typedef long long ll;
#define int ll
typedef vector<int> VI;
typedef vector<VI> VVI;
typedef vector<ll> VL;
typedef vector<VL> VVL;
typedef pair<int, int> PII;

#define FOR(i, a, n) for (ll i = (ll)a; i < (ll)n; ++i)
#define REP(i, n) FOR(i, 0, n)
#define ALL(x) x.begin(), x.end()
#define IN(a, b, x) (a<=x&&x<b)
#define MP make_pair
#define PB push_back
#ifdef int
const int INF = (1LL<<30);
#else
const ll INF = (1LL<<60);
#endif
const double PI = 3.14159265359;
const double EPS = 1e-12;
const int MOD = 1000000007;

template <typename T> T &chmin(T &a, const T &b) { return a = min(a, b); }
template <typename T> T &chmax(T &a, const T &b) { return a = max(a, b); }

int dx[] = {0, 1, 0, -1}, dy[] = {1, 0, -1, 0};

int a[100010], cnt[100010], l[100010], ans[100010];

// xx, yy, zzにそれぞれ座圧する元の配列を突っ込むとx, y, zが座圧された配列で返ってくる
// zip[座圧前] = 座圧後、unzip[座圧後] = 座圧前
VL xx, x, unzip(100010);
unordered_map<int, int> zip;
void compress() {
  x = xx;
  sort(ALL(xx));
  xx.erase(unique(ALL(xx)), xx.end());
  REP(i, xx.size()) {zip[xx[i]] = i; unzip[i] = xx[i];}
  REP(i, x.size()) x[i] = zip[x[i]];
}

signed main(void)
{
  int n;
  cin >> n;
  REP(i, n) {
    cin >> a[i];
    xx.PB(a[i]);
  }
  compress();

  memset(l, -1, sizeof(l));
  int ma = 0;
  REP(i, n) {
    chmax(ma, (int)x[i]);
    cnt[x[i]]++;
    if(l[x[i]] == -1) l[x[i]] = i;
  }
  for(int i=ma; i>=1; --i) cnt[i-1] += cnt[i];
  int mi = INF;
  for(int i=ma; i>=0; --i) {
    chmin(mi, l[i]);
    l[i] = mi;
  }
  REP(i, ma+1) {
    int tmp = i==0 ? xx[i] : xx[i] - xx[i-1];
    ans[l[i]] += cnt[i] * tmp;
  }

  REP(i, n) cout << ans[i] << endl;

  return 0;
}