import std.stdio, std.conv, std.string, std.bigint;
import std.math, std.random, std.datetime;
import std.array, std.range, std.algorithm, std.container, std.format;
string read(){ static string[] ss; while(!ss.length) ss = readln.chomp.split; string res = ss[0]; ss.popFront; return res; }

int n;
long d;

class Node{
	static Edge[] edges;
	int id;
	long value;
	long leftPos, rightPos; // 塔を左に倒したときと右に倒したときの先端の位置
	long[int] costTo;
	Group group;
	this(int id, long value){
		this.id = id;
		this.group = new Group(id, this);
		this.value = value;
		this.leftPos = id * d - value;
		this.rightPos = id * d + value;
	}
	void setCostTo(Node nd){
		if(this.id <= nd.id){
			long cost = nd.rightPos - this.leftPos;
			this.costTo[nd.id] = cost;
			nd.costTo[this.id] = cost;
			edges ~= new Edge(this, nd, cost);
		}
		else nd.setCostTo(this);
	}
	override string toString(){
		return "\n " ~ id.to!string ~ "(" ~ value.to!string ~ "): (" ~ leftPos.to!string ~ ", " ~ rightPos.to!string ~ ") " ~ costTo.to!string ~ " @" ~ group.id.to!string;
	}
}

class Group{
	int id;
	Node[] nodes;
	this(int id, Node node){
		this.id = id;
		this.nodes ~= node;
	}
	void add(Node nd){
		this.nodes ~= nd;
	}
	void eat(Group gp){
		foreach(nd; gp.nodes){
			nd.group = this;
			this.nodes ~= nd;
		}
	}
	long size(){
		return nodes.length;
	}
}


class Edge{
	Node leftNode, rightNode;
	long cost;
	bool isUsed;
	this(Node nd1, Node nd2, long cost){
		if(nd1.id <= nd2.id) this.leftNode = nd1, this.rightNode = nd2;
		else this.leftNode = nd2, this.rightNode = nd1;
		this.cost = cost;
	}
	override string toString(){
		return leftNode.id.to!string ~ "-" ~ rightNode.id.to!string ~ " (" ~ cost.to!string ~ ") " ~ (isUsed? "*": " ");
	}
}



/*

D間隔で、高さAの塔が立っていると見る

Aを、距離のほうに織り込む。
そのために、左から見たときの「最も近い」都市と、右から見たときの「最も近い」都市を持つ

*/

void main(){
	n = read.to!int;
	d = read.to!long;
	
	long[] as;
	foreach(i; 0 .. n) as ~= read.to!long;
	debug writeln("as: ", as);
	
	Node[] nodes;
	foreach(i; 0 .. n) nodes ~= new Node(i, as[i]);
	debug writeln("nodes: ", nodes);
	
	// 左から見ていく。
	// その時点で一番近いノードと結ぶ辺だけを候補にする
	Node rightmostLeftNode = nodes[0];
	foreach(i; 1 .. n){
		Node nd = nodes[i];
		nd.setCostTo(rightmostLeftNode);
		if(nd.leftPos > rightmostLeftNode.leftPos) rightmostLeftNode = nd;
	}
	debug writeln("nodes: ", nodes);
	
	// 右から見ていく。
	// その時点で一番近いノードと結ぶ辺だけを候補にする
	Node leftmostRightNode = nodes[$ - 1];
	foreach_reverse(i; 0 .. n - 1){
		Node nd = nodes[i];
		nd.setCostTo(leftmostRightNode);
		if(nd.rightPos < leftmostRightNode.rightPos) leftmostRightNode = nd;
	}
	debug writeln("nodes: ", nodes);
	
	// クラスカル法
	
	Node.edges.sort!"a.cost < b.cost"();
	
	foreach(ed; Node.edges){
		debug writeln("edge: ", ed);
		
		Node left = ed.leftNode, right = ed.rightNode;
		if(left.group.id == right.group.id) continue;
		
		// edを使って接続する
		ed.isUsed = 1;
		if(left.group.size > right.group.size) left.group.eat(right.group);
		else right.group.eat(left.group);
		
		debug writeln("nodes: ", nodes);
	}
	
	long ans;
	foreach(ed; Node.edges) if(ed.isUsed) ans += ed.cost;
	
	ans.writeln;
	

}
