#include <bits/stdc++.h>
#include <sys/types.h>
#include <unistd.h>

#define _overload(_1,_2,_3,name,...) name
#define _rep(i,n) _range(i,0,n)
#define _range(i,a,b) for(int i=int(a);i<int(b);++i)
#define rep(...) _overload(__VA_ARGS__,_range,_rep,)(__VA_ARGS__)

#define _rrep(i,n) _rrange(i,n,0)
#define _rrange(i,a,b) for(int i=int(a)-1;i>=int(b);--i)
#define rrep(...) _overload(__VA_ARGS__,_rrange,_rrep,)(__VA_ARGS__)

#define _all(arg) begin(arg),end(arg)
#define uniq(arg) sort(_all(arg)),(arg).erase(unique(_all(arg)),end(arg))
#define getidx(ary,key) lower_bound(_all(ary),key)-begin(ary)
#define clr(a,b) memset((a),(b),sizeof(a))
#define bit(n) (1LL<<(n))
#define popcount(n) (__builtin_popcountll(n))

using namespace std;

template<class T>bool chmax(T &a, const T &b) { return (a<b)?(a=b,1):0;}
template<class T>bool chmin(T &a, const T &b) { return (b<a)?(a=b,1):0;}

using ll=long long;
using R=long double;
const R EPS=1e-9L; // [-1000,1000]->EPS=1e-8 [-10000,10000]->EPS=1e-7
inline int sgn(const R& r){return(r > EPS)-(r < -EPS);}
inline R sq(R x){return sqrt(max(x,0.0L));}

const int dx[8]={1,0,-1,0,1,-1,-1,1};
const int dy[8]={0,1,0,-1,1,1,-1,-1};

const pid_t pid = getpid();
// Problem Specific Parameter:

using pll = pair<ll,ll>;
const ll inf = 1LL << 60;

template <int depth> struct Segment_tree {
	const static int h = depth;
	const static int n = 1 << h;

	using T = pll;
	T data[2 * n];
	const T out = pll(inf, -1);

	inline T vmerge(T l, T r) {return min(l, r);}

	void init() {
		fill_n(data, 2 * n, out);
	}

	void update(int p, ll val) { // set value at position p
		for (data[p += n] = pll(val, p); p > 1; p >>= 1){
			data[p >> 1] = vmerge(data[p], data[p ^ 1]);
		}
	}

	T query(int l, int r) {  // sum on interval [l, r)
		T resl = out, resr = out;
		for (l += n, r += n; l < r; l >>= 1, r >>= 1) {
			if (l & 1) resl = vmerge(data[l++], resl);
			if (r & 1) resr = vmerge(resr, data[--r]);
		}
		return vmerge(resl, resr);
	}
};

// Description: 素集合を管理するデータ構造
// TimeComplexity: 初期化$\mathcal{O}(n)$ 更新$\mathcal{O}(\log n)$
// Verifyed: AOJ DSL_1_A

struct Union_find {
	Union_find(int n) {data.assign(n, -1);}
	int find(int x) {return (data[x] < 0) ? x : data[x] = find(data[x]);}
	void unite(int a, int b) {
		a = find(a), b = find(b);
		if (a != b) {
			if (data[a] < data[b]) swap(a, b);
			data[a] += data[b], data[b] = a;
		}
	}
	bool same(int a, int b) {return find(a) == find(b);}
	int size(int x) {return -data[x];}
	vector<int> data;
};

Segment_tree<18> lft, rht;

int main(void){
	ll n, d;
	cin >> n >> d;
	vector<pll> ary;

	rep(i, n){
		ll val;
		cin >> val;
		ary.push_back(pll(val, i));
	}

	sort(begin(ary), end(ary));

	using edge = tuple<ll,ll,ll>;
	vector<edge> graph;

	
	lft.init(), rht.init();

	for(auto &elem:ary){
		const ll a = elem.first;
		const ll x = elem.second;

		auto lmin = lft.query(0, x);
		
		if(lmin.second != -1){
			const ll c = lmin.first + a + d * x;
			graph.push_back(edge(c, x, lmin.second));
		}

		auto rmin = rht.query(x + 1, n);

		if(rmin.second != -1){
			const ll c = rmin.first + a - d * x;
			graph.push_back(edge(c, x, rmin.second));
		}

		lft.update(x, a - d * x);
		rht.update(x, a + d * x);
	}

	sort(begin(graph), end(graph));

	ll ans = 0LL;
	Union_find uf(n);

	for(auto &e:graph){
		ll c,a, b;
		tie(c, a, b) = e;
		if(uf.same(a, b)) continue;
		uf.unite(a, b);
		ans += c;
	}

	cout << ans << endl;

	return 0;
}

Measured memory_bytes: 37096