#define _USE_MATH_DEFINES
#include <cstdio>
#include <iostream>
#include <sstream>
#include <fstream>
#include <iomanip>
#include <algorithm>
#include <cmath>
#include <complex>
#include <string>
#include <vector>
#include <array>
#include <list>
#include <queue>
#include <stack>
#include <set>
#include <map>
#include <bitset>
#include <numeric>
#include <limits>
#include <climits>
#include <cfloat>
#include <functional>
#include <iterator>
#include <memory>
#include <regex>
using namespace std;

const long long INF = LLONG_MAX / 2;

class SegmentTree
{
public:
    typedef pair<long long, int> T1;
    typedef long long T2;

    // データの初期値、以下の条件を満たすこと
    //   uniteData(v, INIT_DATA) == v
    static const T1 INIT_DATA;

    // 2つの区間の計算結果v1,v2に対して、
    // その2つの区間を統合した区間における計算結果を返す
    static T1 uniteData(T1 v1, T1 v2){
        return min(v1, v2);
    }

private:
    // 前回の値がprevである要素に対して、
    // パラメータxを用いた更新処理を適用した後の計算結果を返す
    T1 updateData(T1 prev, T2 x){
        prev.first = x;
        return prev;
    }

    int n;
    vector<T1> data;
    void updateTree(int a, int k, int l, int r, T2 x){
        if(a == l && a == r){
            data[k] = updateData(data[k], x);
        }
        else if(l <= a && a <= r){
            updateTree(a, k*2+1, l, (l+r)/2, x);
            updateTree(a, k*2+2, (l+r+1)/2, r, x);
            data[k] = uniteData(data[k*2+1], data[k*2+2]);
        }
    }
    T1 getValue(int a, int b, int k, int l, int r){
        if(a <= l && r <= b){
            return data[k];
        }
        else if(a <= r && l <= b){
            T1 v1 = getValue(a, b, k*2+1, l, (l+r)/2);
            T1 v2 = getValue(a, b, k*2+2, (l+r+1)/2, r);
            return uniteData(v1, v2);
        }
        else{
            return INIT_DATA;
        }
    }

public:
    SegmentTree(int n0){
        n = 1;
        while(n < n0)
            n *= 2;
        data.assign(2*n-1, INIT_DATA);
    }
    SegmentTree(const vector<T1>& v) : SegmentTree((int)v.size()){
        for(unsigned i=0; i<v.size(); ++i)
            data[n-1+i] = v[i];
        for(int k=n-2; k>=0; --k)
            data[k] = uniteData(data[k*2+1], data[k*2+2]);
    }
    // a番目の要素にパラメータxによる更新処理を適用
    void update(int a, T2 x){
        updateTree(a, 0, 0, n-1, x);
    }
    // 区間[a,b]の計算結果を返す
    T1 get(int a, int b){
        return getValue(a, b, 0, 0, n-1);
    }
};
const SegmentTree::T1 SegmentTree::INIT_DATA(INF, -1);

class UnionFindTree
{
private:
    int n;
    vector<int> parent; // 親ノード
    vector<int> rank;   // 木の高さの上限
public:
    int find(int i){
        if(i == -1)
            return -1;
        else if(parent[i] == i)
            return i;
        else
            return parent[i] = find(parent[i]);
    }
    UnionFindTree(int n){ // コンストラクタ
        this->n = n;
        parent.resize(n);
        for(int i=0; i<n; ++i)
            parent[i] = i;
        rank.assign(n, 0);
    }
    void unite(int a, int b){ // aとbのグループを併合
        if((a = find(a)) != (b = find(b))){
            if(rank[a] < rank[b]){
                parent[a] = b;
            }
            else{
                parent[b] = a;
                if(rank[a] == rank[b])
                    ++ rank[a];
            }
        }
    }
    bool same(int a, int b){ // aとbのグループが同じかを調べる
        return find(a) == find(b);
    }
};

long long solve(const vector<long long>& a, long long d)
{
    int n = a.size();
    vector<pair<long long, int> > v(n), tmp(n);
    for(int i=0; i<n; ++i){
        v[i].first = a[i];
        v[i].second = i;
        tmp[i].first = INF;
        tmp[i].second = i;
    }
    sort(v.begin(), v.end());

    SegmentTree st1(tmp), st2(tmp);
    multiset<tuple<long long, int, int> > ms;
    for(const auto& p : v){
        int i = p.second;

        auto x = st1.get(i+1, n-1);
        if(x.first < INF){
            int j = x.second;
            long long cost = x.first + a[i] - d * i;
            ms.insert(make_tuple(cost, i, j));
        }
        st1.update(i, a[i] + d * i);

        auto y = st2.get(0, i-1);
        if(y.first < INF){
            int j = y.second;
            long long cost = y.first + a[i] - d * (n - 1 - i);
            ms.insert(make_tuple(cost, i, j));
        }
        st2.update(i, a[i] + d * (n - 1 - i));
    }

    long long ans = 0;
    UnionFindTree uft(n);
    for(const auto& t : ms){
        long long cost;
        int i, j;
        tie(cost, i, j) = t;
        if(!uft.same(i, j)){
            ans += cost;
            uft.unite(i, j);
        }
    }
    return ans;
}

int main()
{
    int n;
    long long d;
    cin >> n >> d;
    vector<long long> a(n);
    for(int i=0; i<n; ++i)
        cin >> a[i];

    cout << solve(a, d) << endl;

    return 0;
}


Measured memory_bytes: 50944