// vvvvvvvvvvvv TEMPLATE vvvvvvvvvvvv
#include <bits/stdc++.h>
using namespace std; using ll = long long; using P = pair<ll, ll>;
const ll linf = 1e18; const double eps = 1e-12, pi = acos(-1);
#define FOR(i,a,b) for (ll i=(a),__last_##i=(b);i<__last_##i;i++)
#define RFOR(i,a,b) for (ll i=(b)-1,__last_##i=(a);i>=__last_##i;i--)
#define REP(i,n) FOR(i,0,n)
#define RREP(i,n) RFOR(i,0,n)
#define __GET_MACRO3(_1, _2, _3, NAME, ...) NAME
#define each(i,a) for (auto&& i : a)
#define rep(...) __GET_MACRO3(__VA_ARGS__, FOR, REP)(__VA_ARGS__)
#define rrep(...) __GET_MACRO3(__VA_ARGS__, RFOR, RREP)(__VA_ARGS__)
#define pb push_back
#define eb emplace_back
#define all(a) begin(a),end(a)
#define chmin(x,v) x = min(x, v)
#define chmax(x,v) x = max(x, v)
#define min(x,y) (x < y ? x : y)
#define max(x,y) (x < y ? y : x)
template<typename Head> void out(Head h) { cout << h << endl; } template<typename Head, typename... Tail>void out(Head h, Tail... t) { cout << h << " "; out(t...); }
template<typename T> istream& operator>>(istream& is, vector<T>& v) { each(x,v) is >> x; return is; }
template<typename T> ostream& operator<<(ostream& os, const vector<T>& v) { rep(i,v.size()) { if (i) os << " "; os << v[i]; } return os; }
ostream& operator<<(ostream& os, const vector<string>& v) { rep(i,v.size()) { if (i) os << endl; os << v[i]; } return os; }
template<typename T> ostream& operator<<(ostream& os, const vector<vector<T>>& v) { rep(i,v.size()) { if (i) os << endl; os << v[i]; } return os; }
template<typename T1, typename T2> ostream& operator<<(ostream& os, const pair<T1, T2>& p) { return os << "(" << p.first << ", " << p.second << ")"; }
struct yes_no : std::numpunct<char> { string_type do_truename() const { return "Yes"; } string_type do_falsename() const { return "No"; } };
void solve(); int main() {
  ios::sync_with_stdio(false); cin.tie(0); locale loc(locale(), new yes_no); cout.imbue(loc); cout << fixed << setprecision(10) << boolalpha;
  solve();
}
// ^^^^^^^^^^^^ TEMPLATE ^^^^^^^^^^^^

class UnionFind {
  vector<ll> par, h, sz;
public:
  UnionFind(ll size) : par(size, 0), h(size, 0), sz(size, 1) {
    rep(i, size) par[i] = i;
  }
  void unite(ll u, ll v) {
    u = root(u), v = root(v);
    if (u == v) return;
    if (h[u] < h[v]) {
      par[u] = v;
      sz[v] += sz[u];
    }
    else {
      par[v] = u;
      sz[u] += sz[v];
    }
    if (h[u] == h[v]) ++h[u];
  }
  ll size(ll v) {
    return sz[root(v)];
  }
  bool isUnited(ll u, ll v) {
    return root(u) == root(v);
  }
  ll root(ll v) {
    if (par[v] == v) return v;
    return par[v] = root(par[v]);
  }
};

struct Edge {
  ll a, b, c;
};
bool operator<(const Edge& e1, const Edge& e2) {
  return e1.c < e2.c;
}

template <class Monoid>
class SegmentTree {
  using T = typename Monoid::type;
  const int size_, n;
  std::vector<T> data;
  int expand(int m) const { return m <= 1 ? 1 : expand((m + 1) / 2) * 2; }
public:
  SegmentTree() : SegmentTree(0) {}
  SegmentTree(const std::vector<T> &vec) :
    size_(vec.size()), n(expand(size_)), data(n * 2, Monoid::id()) {
    std::copy(begin(vec), end(vec), begin(data) + n);
    for (int i = n - 1; i >= 0; --i) {
      data[i] = Monoid::op(data[i * 2 + 0], data[i * 2 + 1]);
    }
  }
  SegmentTree(const int count, const T &value = Monoid::id()) :
    SegmentTree(std::vector<T>(count, value)) {}
  int size() const { return size_; }
  void update(int pos, const T &value) {
    assert (0 <= pos && pos < size_); // assertion
    data[pos += n] = value;
    while (pos /= 2) {
      data[pos] = Monoid::op(data[pos * 2], data[pos * 2 + 1]);
    }
  }
  T find(int l, int r) const {
    assert (0 <= l && l <= r && r <= size_); // assertion
    l += n; r += n;
    T res1 = Monoid::id(), res2 = Monoid::id();
    while (l != r) {
      if (l % 2) res1 = Monoid::op(res1, data[l++]);
      if (r % 2) res2 = Monoid::op(data[--r], res2);
      l /= 2; r /= 2;
    }
    return Monoid::op(res1, res2);
  }
  using value_type = T;
  using update_type = T;
};

struct Min {
  using type = P;
  static type id() { return P(linf, linf); }
  static type op(const type &l, const type &r) { return min(l, r); }
};
struct Max {
  using type = ll;
  static type id() { return -linf; }
  static type op(const type &l, const type &r) { return max(l, r); }
};
struct Sum {
  using type = ll;
  static type id() { return 0; }
  static type op(const type &l, const type &r) { return l + r; }
};

void solve() {
  ll n, D; cin >> n >> D;
  vector<ll> a(n); cin >> a;
  vector<ll> ra(n), la(n);
  rep(i, n) {
    ra[i] = -i * D + a[i];
    la[i] = i * D + a[i];
  }
  ll ans = 0;
  UnionFind uf(n);
  while (uf.size(0) != n) {
    vector<vector<ll>> v(n);
    rep(i, n) {
      v[uf.root(i)].pb(i);
    }
    vector<P> segl0(n), segr0(n);
    rep(i, n) {
      segl0[i] = P(ra[i], i);
      segr0[i] = P(la[i], i);
    }
    SegmentTree<Min> segl(segl0), segr(segr0);
    rep(i, n) {
      if (v[i].size() == 0) continue;
      // 削除
      each(j, v[i]) {
        segl.update(j, P(linf, j));
        segr.update(j, P(linf, j));
      }
      P p(linf, linf);
      each(j, v[i]) {
        P p1 = segl.find(0, j);
        p1.first += la[j];
        P p2 = segr.find(j+1, n);
        p2.first += ra[j];
        chmin(p, min(p1, p2));
      }
      assert(p.first != linf);
      if (!uf.isUnited(i, p.second)) {
        uf.unite(i, p.second);
        ans += p.first;
      }
      // 追加
      each(j, v[i]) {
        segl.update(j, segl0[j]);
        segr.update(j, segr0[j]);
      }
    }
  }
  cout << ans << endl;
}


Measured memory_bytes: 43264