#include <bits/stdc++.h>
#define FOR(i, begin, end) for(int i=(begin);i<(end);i++)
#define REP(i, n) FOR(i,0,n)
#define IFOR(i, begin, end) for(int i=(end)-1;i>=(begin);i--)
#define IREP(i, n) IFOR(i,0,n)
#define SORT(a) sort(a.begin(), a.end())
#define REVERSE(a) reverse(a.begin(), a.end())
#define Lower_bound(v, x) distance(v.begin(), lower_bound(v.begin(), v.end(), x))
#define Upper_bound(v, x) distance(v.begin(), upper_bound(v.begin(), v.end(), x))
#define int long long
#define INF 1000000000000000000
using namespace std;

#define ANS(f) if(f) cout << "YES" << endl; else cout << "NO" << endl;

typedef vector<int> vec;
typedef vector<vec> mat;
typedef pair<int, int> Pii;
typedef pair<int, Pii> PiP;

template<typename T>
void readv(vector<T> &a){ REP(i, a.size()) cin >> a[i]; }
void readi(vector<int> &a){ REP(i, a.size()){cin >> a[i]; a[i]--;} }
void debug(mat m){REP(i, m.size()){ REP(j, m[i].size()){ cout << m[i][j] << ","; } cout << endl; }}

class Segment_tree
{
    using data_type = Pii;

public:

    vector<data_type> dat;
    int N;
    data_type id;

    data_type func(data_type u, data_type v){
        return min(u, v);
    }

    Segment_tree(int n, data_type id): id(id) {
        N = 1;
        while(n > N) N = N << 1;
        dat = vector<data_type>(2 * N - 1, id);
    }

    Segment_tree(int n, data_type id, vector<data_type> v): id(id) {
        N = 1;
        while(n > N) N = N << 1;
        dat = vector<data_type>(2 * N - 1, id);
        REP(i, n) dat[i + N - 1] = v[i];
        IREP(i, N - 1) dat[i] = func(dat[i * 2 + 1], dat[i * 2 + 2]); 
    }

    //k番目の値をaに更新
    void update(int k, data_type a){
        k += N - 1;
        dat[k] = a;
        while(k > 0){
            k = (k - 1) / 2;
            dat[k] = func(dat[k * 2 + 1], dat[k * 2 + 2]);
        }
    }

    data_type query(int a, int b, int k, int l, int r){
        if(r <= a || b <= l) return id;
        if(a <= l && r <= b) return dat[k];
        else{
            data_type vl = query(a, b, k * 2 + 1, l, (l + r) / 2);
            data_type vr = query(a, b, k * 2 + 2, (l + r) / 2, r);
            return func(vl, vr);
        }
    }

    //[a, b)の演算結果
    data_type query(int a, int b){
        return query(a, b, 0, 0, N);
    }

    data_type getdat(int k){
        return dat[k + N - 1];
    }
};

class union_find final
{
    using data_type = int64_t;
    using size_type = uint64_t;

    data_type none = -1;

    // data_[index]の値が親要素を表す(noneはroot)
    std::vector<data_type> data_;
    // rootの集合
    std::set<data_type> roots_;
    // そのグループの要素の数
    std::vector<size_type> size_;

    // indexのrootを求める
    data_type root(data_type index)
    {
        // グループ番号がnoneならそれがroot
        if(data_[index] == none)
            return index;
        // 親へのindexをrootに付け替える(高速化)
        data_[index] = root(data_[index]);
        return data_[index];
    }
public:

    union_find(data_type size)
        : data_(size, none), size_(size, 1)
    {
    }

    // aとbを同じグループにする
    void unite(data_type a, data_type b)
    {
        a = root(a);
        b = root(b);
        
        // aとbのrootが同じならすでに同じグループ
        if(a == b) return;
        
        // 要素の多い方に付け替える(高速化)
        if(size_[a] < size_[b]) {
            data_[b] = a;
            size_[a] = size_[a] + size_[b];
            roots_.erase(b);
            roots_.insert(a);
        } else {
            data_[a] = b;
            size_[b] = size_[a] + size_[b];
            roots_.erase(a);
            roots_.insert(b);
        }
    }

    bool is_union(data_type a, data_type b)
    {
        return root(a) == root(b);
    }
    
    // ↓あると便利なの

    const std::set<data_type>& roots() const
    {
        return roots_;
    }

    size_type maximum() const
    {
        return *std::max_element(size_.begin(), size_.end());
    }
    size_type minimum() const
    {
        return *std::min_element(size_.begin(), size_.end());
    }
};

signed main(){

    int N, D; cin >> N >> D;
    vector<Pii> A(N);
    REP(i, N){
        cin >> A[i].first;
        A[i].second = i;
    }
    SORT(A);
    Segment_tree Sp(N, Pii(INF, INF)), Sm(N, Pii(INF, INF));

    priority_queue<PiP, vector<PiP>, greater<PiP>> que;

    REP(i, N){
        int a = A[i].first;
        int i0 = A[i].second;

        Pii p1 = Sp.query(i0 + 1, N);
        if(p1.first < INF){
            que.push(PiP(a + p1.first - i0 * D, Pii(i0, p1.second)));
        }
        Pii p2 = Sm.query(0, i0);
        if(p2.first < INF){
            que.push(PiP(a + p2.first + i0 * D, Pii(i0, p2.second)));
        }

        Sp.update(i0, Pii(a + i0 * D, i0));
        Sm.update(i0, Pii(a - i0 * D, i0));
    }

    union_find U(N);
    int ans = 0;
    while(!que.empty()){
        PiP tmp = que.top(); que.pop();
        int v1 = tmp.second.first, v2 = tmp.second.second;
        if(!U.is_union(v1, v2)){
            ans += tmp.first;
            U.unite(v1, v2);
        }
    }
    cout << ans;
    
    return 0;
}

Measured memory_bytes: 35560