#include <iostream>
#include <vector>
#include <algorithm>
#include <set>
#include <string>
#include <cstring>
#include <map>
using namespace std;

template <typename monoid>
struct segment_tree {
    using M = monoid;
    using T = typename M::value_type;

    std::size_t sz;
    std::vector<T> x;

    segment_tree(std::size_t n = 0) {
        sz = 1;
        while (sz < n) sz *= 2;
        x.assign(sz * 2, M::id());
        initialize();
    }

    template <typename iterator>
    segment_tree(iterator first, iterator last) {
        sz = 1;
        std::size_t n = std::distance(first, last);
        while (sz < n) sz *= 2;
        x.assign(sz * 2, M::id());
        std::copy(first, last, x.begin() + sz);
        initialize();
    }

    void fill(const T &val) {
        std::fill(x.begin() + sz, x.end(), val);
        initialize();
    }

    void initialize() {
        for (int i = (int)sz - 1; i >= 1; --i) {
            x[i] = M::op(x[i * 2 + 0], x[i * 2 + 1]);
        }
    }

    T accumulate(std::size_t l, std::size_t r) const {
        T al = M::id(), ar = M::id();
        for (l += sz, r += sz; l < r; l /= 2, r /= 2) {
            if (l & 1) al = M::op(al, x[l++]);
            if (r & 1) ar = M::op(x[--r], ar);
        }
        return M::op(al, ar);
    }

    void update(std::size_t i, const T &val) {
        x[i += sz] = val;
        while (i > 1) {
            x[i / 2] = M::op(x[i], x[i ^ 1]);
            i /= 2;
        }
    }

    T operator[](std::size_t i) const { return x[sz + i]; }
};

struct min_monoid {
    using P = pair<int64_t, int>;
    using value_type = P;

    static constexpr P id() { return make_pair((int64_t)(1LL << 50), -1); }
    static P op(const P &a, const P &b) { return std::min(a, b); }
};

struct uf_tree {
    std::vector<int> parent;
    int __size;
    uf_tree(int size_) : parent(size_, -1), __size(size_) {}
    void unite(int x, int y) {
        if ((x = find(x)) != (y = find(y))) {
            if (parent[y] < parent[x]) std::swap(x, y);
            parent[x] += parent[y];
            parent[y] = x;
            __size--;
        }
    }
    bool is_same(int x, int y) { return find(x) == find(y); }
    int find(int x) { return parent[x] < 0 ? x : parent[x] = find(parent[x]); }
    int size(int x) { return -parent[find(x)]; }
    int size() { return __size; }
};


struct Edge {
  int u, v;
  int64_t cost;

  Edge() = default;
  Edge(int u, int v, int64_t cost): u(u), v(v), cost(cost) {}
  bool operator<(const Edge& e) const {
    return cost < e.cost;
  }
};

int main() {
  cin.tie(nullptr);
  ios::sync_with_stdio(false);

  int n;
  int64_t d;
  cin >> n >> d;

  vector<int64_t> a(n);
  for (int i = 0; i < n; i++) {
    cin >> a[i];
  }

  vector<int> indices(n);
  for (int i = 0; i < n; i++) {
    indices[i] = i;
  }

  sort(indices.begin(), indices.end(),
        [&](int i, int j) { return a[i] < a[j]; });

  using P = pair<int64_t, int>;

  segment_tree<min_monoid> seg1(n), seg2(n);
  vector<Edge> edges;

  for (int idx : indices) {
    if (idx + 1 < n) {
      P elem = seg1.accumulate(idx + 1, n);

      int64_t cost = elem.first - d * idx + a[idx];
      int end = elem.second;

      edges.emplace_back(idx, end, cost);
    }
    if (idx > 0) {
      P elem = seg2.accumulate(0, idx);

      int64_t cost = elem.first - d * (n - 1 - idx) + a[idx];
      int end = elem.second;

      edges.emplace_back(idx, end, cost);
    }

    seg1.update(idx, make_pair(d * idx + a[idx], idx));
    seg2.update(idx, make_pair(d * (n - 1 - idx) + a[idx], idx));
  }

  sort(edges.begin(), edges.end());

  uf_tree union_find(n);

  int64_t ans = 0;
  for (Edge& e : edges) {
    if (e.v < 0 or e.v >= n or union_find.is_same(e.u, e.v)) continue;
    union_find.unite(e.u, e.v);
    ans += e.cost;
  }
  cout << ans << endl;

  return 0;
}

Measured memory_bytes: 29292