#define _USE_MATH_DEFINES
#include <bits/stdc++.h>
using namespace std;
typedef long long ll;
typedef unsigned long long ull;
typedef long double ld;
using P   = pair<ll, ll>;
using mat = vector<vector<ll>>;

void IOS() { ios::sync_with_stdio(false), cin.tie(0); }

const ll INF = 1e18;
const ll MOD = 1e9 + 7;
const ld EPS = 1e-12;

template <typename T>
void dump(T x) { cout << x << endl; }
void dumpf(ld x, int t) { cout << setprecision(t) << fixed << x << endl; }
template <typename A, size_t N, typename T>
void Fill(A (&array)[N], const T &val) {
	fill((T *)array, (T *)(array + N), val);
}
inline ll mod(ll a, ll b) {
	if (a > 0) return a % b;
	if (a % b == 0) return 0;
	ll x = -a / b + 1;
	a += x * b;
	return a % b;
}
ll gcd(ll a, ll b) {
	if (b == 0) return a;
	return gcd(b, a % b);
}

// ll dx[4] = {1, 0, -1, 0};
// ll dy[4] = {0, 1, 0, -1};

struct edge {
	ll from, to, cost;
	bool operator<(edge &e) {
		return (cost < e.cost);
	}
};

template <class Monoid>
class SegTree {
	using OP = std::function<Monoid(Monoid, Monoid)>;

  private:
	int n;
	std::vector<Monoid> dat;
	OP op;
	Monoid e;

  public:
	SegTree(int n_, OP op, Monoid e) : op(op), e(e) {
		n = 1;
		while (n < n_) {
			n *= 2;
		}
		dat.resize(2 * n);
		for (int i = 0; i < 2 * n - 1; i++) {
			dat[i] = e;
		}
	}
	void update(int k, Monoid v) {
		k += n - 1;
		dat[k] = v;
		while (k > 0) {
			k	  = (k - 1) / 2;
			dat[k] = op(dat[2 * k + 1], dat[2 * k + 2]);
		}
	}
	Monoid querySub(int a, int b) const {
		Monoid left  = e;
		Monoid right = e;
		a += n - 1;
		b += n - 1;
		while (a < b) {
			if ((a & 1) == 0) {
				left = op(left, dat[a]);
			}
			if ((b & 1) == 0) {
				right = op(dat[b - 1], right);
			}
			a = a / 2;
			b = (b - 1) / 2;
		}
		return op(left, right);
	}
	Monoid query(int a, int b) const { return querySub(a, b + 1); }
};

struct UnionFind {
  private:
	std::vector<int> rank, par, col;
	int n_;

  public:
	UnionFind(int n) : n_(n) {
		rank.resize(n, 1);
		par.resize(n);
		for (int i = 0; i < n; ++i) {
			par[i] = i;
		}
		col.resize(n, 1);
	}
	int root(int i) {
		while (par[i] != i) {
			i = par[i];
		}
		return i;
	}
	bool isSame(int x, int y) { return root(x) == root(y); }
	void unite(int x, int y) {
		if (isSame(x, y)) return;
		x = root(x), y = root(y);
		if (rank[x] < rank[y]) {
			par[x] = y;
			col[y] += col[x];
		} else {
			if (rank[x] == rank[y]) rank[x]++;
			par[y] = x;
			col[x] += col[y];
		}
	}
	int cnt(int x) {
		x = root(x);
		return col[x];
	}
};

signed main() {
	IOS();
	ll n, d;
	cin >> n >> d;
	vector<P> a(n);
	for (int i = 0; i < n; i++) {
		cin >> a[i].first;
		a[i].second = i + 1;
	}
	sort(a.begin(), a.end());
	vector<edge> s;
	P inf = P(INF, INF);

	function<P(P, P)> f = [](P a, P b) { return min(a, b); };
	SegTree<P> sg1(n + 1, f, inf), sg2(n + 1, f, inf);
	for (int i = 0; i < n; i++) {
		ll x	= a[i].first;
		ll now  = a[i].second;
		P left  = sg1.query(1, now);
		P right = sg2.query(now, n);
		edge e1, e2;
		e1.from = e2.from = now;

		e1.to   = left.second;
		e2.to   = right.second;
		e1.cost = x + now * d + left.first;
		e2.cost = x - now * d + right.first;
		if (e1.to <= n) s.push_back(e1);
		if (e2.to <= n) s.push_back(e2);
		sg1.update(now, P(x - d * now, now));
		sg2.update(now, P(x + d * now, now));
	}
	sort(s.begin(), s.end());

	ll ans = 0;
	UnionFind uf(n + 1);
	for (int i = 0; i < s.size(); i++) {
		//cout << s[i].cost << " " << s[i].to << " " << s[i].from << endl;
		if (!uf.isSame(s[i].from, s[i].to)) {
			ans += s[i].cost;
			uf.unite(s[i].from, s[i].to);
		}
	}
	dump(ans);
	return 0;
}

Measured memory_bytes: 34284