#include <bits/stdc++.h>
using namespace std;
using lint     = long long;
const lint inf = 1LL << 60;
const lint mod = 1000000007;

// 0-indexed bottom up Segment Tree
// UNIT is the identity element of operation func
template <typename T = int>
struct SegmentTree {
    using F = function<T(T, T)>;
    int n;
    vector<T> dat;
    F func;
    T UNIT;

    SegmentTree(int n_, F func_, T UNIT_) : func(func_), UNIT(UNIT_) {
        n = 1;
        // full binary tree: num of leaves = n = 2^k >= n_
        while (n < n_)
            n *= 2;
        dat.assign(2 * n - 1, UNIT);
    }
    SegmentTree(vector<T> v_, F func_, T UNIT_) : func(func_), UNIT(UNIT_) {
        n      = 1;
        int nv = v_.size();
        while (n < nv)
            n *= 2;
        dat.assign(2 * n - 1, UNIT);
        for (int i = 0; i < nv; ++i) {
            dat[n - 1 + i] = v_[i];
        }
        for (int i = n - 2; i >= 0; --i) {
            dat[i] = func(dat[2 * i + 1], dat[2 * i + 2]);
        }
    }
    void update(int k, T a) {
        // leaves are at index n-1 to 2*n-2
        k += n - 1;
        dat[k] = a;
        while (k > 0) {
            // k -> parent node
            k = (k - 1) / 2;
            // func(child nodes)
            dat[k] = func(dat[2 * k + 1], dat[2 * k + 2]);
        }
    }
    // get result of func() in [l, r)
    T query(int l, int r) {
        l += n - 1;
        r += n - 1;
        T retl = UNIT, retr = UNIT;
        while (l < r) {
            if ((l & 1) == 0)
                retl = func(retl, dat[l]);
            if ((r & 1) == 0)
                retr = func(dat[r - 1], retr);
            l = l / 2;
            r = (r - 1) / 2;
        }
        return func(retl, retr);
    }
};
auto f                      = [](pair<lint, lint> l, pair<lint, lint> r) { return min(l, r); };
const pair<lint, lint> unit = {inf, -1};

struct UnionFind {
    vector<int> rank, parent, size;

    // +1 for 1-indexed nodes
    UnionFind(int n) : rank(n + 1, 0), parent(n + 1), size(n + 1, 1) {
        iota(parent.begin(), parent.end(), 0); // parent is itself
    }
    int root(int x) {
        if (x != parent[x]) {
            parent[x] = root(parent[x]);
        }
        return parent[x];
    }
    bool isSame(int x, int y) { return root(x) == root(y); }
    bool unite(int x, int y) { return link(root(x), root(y)); }
    bool link(int x, int y) {
        if (x == y)
            return false;
        if (rank[x] > rank[y]) {
            parent[y] = x;
            size[x] += size[y];
        } else {
            parent[x] = y;
            size[y] += size[x];
            if (rank[x] == rank[y]) {
                rank[y]++;
            }
        }
        return true;
    }
    int getSize(int x) { return size[root(x)]; }
};

// Kruskal algorithm: build minimum spanning tree
template <typename T>
struct Kruskal {
    struct edge {
        int from, to, used;
        T cost;
        edge(int from_, int to_, T cost_) : from(from_), to(to_), used(0), cost(cost_) {}
        bool operator<(const edge &e) const { return cost < e.cost; }
    };
    vector<edge> es;
    UnionFind uf;
    Kruskal(int n) : uf(n + 1) {}
    void addEdge(int f, int t, T c) { es.emplace_back(f, t, c); }
    T build() {
        sort(es.begin(), es.end());
        T res = 0;
        for (auto &e : es) {
            if (!uf.isSame(e.from, e.to)) {
                res += e.cost;
                uf.unite(e.from, e.to);
                e.used = 1;
            }
        }
        return res;
    }
};

int main() {
    cin.tie(nullptr);
    ios::sync_with_stdio(false);
    lint n, d;
    cin >> n >> d;
    vector<lint> a(n);
    vector<pair<lint, lint>> ai(n);
    for (int i = 0; i < n; ++i) {
        cin >> a[i];
        ai[i] = {a[i], i};
    }
    sort(ai.begin(), ai.end());
    SegmentTree<pair<lint, lint>> segl(n, f, unit), segr(n, f, unit);
    segl.update(ai[0].second, {ai[0].first - d * ai[0].second, ai[0].second});
    segr.update(ai[0].second, {ai[0].first + d * ai[0].second, ai[0].second});
    Kruskal<lint> graph(n);
    for (int i = 1; i < n; ++i) {
        auto minil = segl.query(0, ai[i].second);
        auto minir = segr.query(ai[i].second, n);
        if (minil.second != -1) {
            int idx   = minil.second;
            int aa    = a[idx];
            lint cost = ai[i].first + aa + abs(ai[i].second - idx) * d;
            graph.addEdge(idx, ai[i].second, cost);
        }
        if (minir.second != -1) {
            int idx   = minir.second;
            int aa    = a[idx];
            lint cost = ai[i].first + aa + abs(ai[i].second - idx) * d;
            graph.addEdge(idx, ai[i].second, cost);
        }
        segl.update(ai[i].second, {ai[i].first - d * ai[i].second, ai[i].second});
        segr.update(ai[i].second, {ai[i].first + d * ai[i].second, ai[i].second});
    }
    cout << graph.build() << "\n";
    return 0;
}

Measured memory_bytes: 37996