###template###
import sys
def input(): return sys.stdin.readline().rstrip()
import heapq
INF = float("inf")
def mi(): return map(int, input().split())
def ii(): return int(input())
###template###

N, D = mi()

#As[i] = [各都市のコスト,各都市の番号]
#0-indexed
As = [[a, i] for i, a in enumerate(list(mi()))]

#Union-Find ****0スタートなので注意！****
class UnionFind():
  # 作りたい要素数（ノードの数）nで初期化
  # 使用するインスタンス変数の初期化
  def __init__(self, n):
    self.n = n
    # root[x]<0ならそのノードが根かつその値が木の要素数
    # rootノードでその木の要素数を記録する
    self.root = [-1]*(n) #元々はn+1になっていたが、nにした（n+1なら1スタートで使えるかもしれないが、Count_Trees()がおかしくなるのでやめた）
    # 木をくっつける時にアンバランスにならないように調整する
    self.rnk = [0]*(n) #元々はn+1になっていたが、nにした

  # ノードxのrootノードを見つける
  def Find_Root(self, x):
    if(self.root[x] < 0):
      return x
    else:
      # ついでに経路圧縮（調べた辺を根に直接つなぎ直す）をかけておく
      self.root[x] = self.Find_Root(self.root[x])
      return self.root[x]
  # 木の併合、入力は併合したい集合に属する各ノード
  def Unite(self, x, y):
    # 入力ノードのrootノードを見つける
    x = self.Find_Root(x)
    y = self.Find_Root(y)
    # すでに同じ木に属していた場合、何もしないで返す
    if(x == y):
      return
    # 違う木に属していた場合rnkを見てくっつける方を決める
    elif(self.rnk[x] > self.rnk[y]):
      self.root[x] += self.root[y] #要素数を足す(根のrootは"-要素数")
      self.root[y] = x #ノードyの親をx（新しい集合の根）とする
      return 1
    else:
      self.root[y] += self.root[x] #要素数を足す
      self.root[x] = y
      # rnkが同じ（深さに差がない場合）は1増やす（根(rnk1)+繋げる集合のrnkということで、1増えることになる）
      if(self.rnk[x] == self.rnk[y]):
          self.rnk[y] += 1
      return 1

  # xとyが同じグループに属するか判断
  def isSameGroup(self, x, y):
    return self.Find_Root(x) == self.Find_Root(y)
  # ノードxが属する木のサイズを返す（根ノードの.root[idx]を-符号を外して返すだけ
  def Count(self, x):
    return -self.root[self.Find_Root(x)] #-符号を外す

#As_規模降順 = [各都市の規模, 各都市の番号（降順ソート前の番号）]
from operator import itemgetter
As_costdescending = sorted(As, key=itemgetter(0), reverse=True)

#やっぱSegTree使う
seg_length = N
bitlen = (seg_length-1).bit_length() #number of raws except 1st row
N0 = 2**bitlen #length of lowest 
#INF = 2**31-1 #自分のtemplateで宣言してるのでいらない
data = [[INF,0] for _ in range(2*N0)]
#各ノードにおける最小値のidxの初期値を格納
for i in range(1, bitlen+1): #(0は除き)1,2,3段目に行う iは段数を表す
  for j in range(0,2**i): #一番左は0のまま、残りはidxを変える
    #i段目の左端のidxは2**i-1
    data[2**i-1 + j][1] = (2**(bitlen-i))*j
#receive arr and initialize segtree
#not necessarily needed
def segfy(arr):
  i = 0
  for val in arr: #update lowest
    data[i+N0-1][0] = val
    i += 1
  #i is row number
  for i in range(bitlen-1, -1, -1):
    k = 2**i - 1 #idx
    for j in range(0,2**i):
      if data[2*k+1][0]<=data[2*k+2][0]:
    	  data[k] = [data[2*k+1][0],data[2*k+1][1]]
      else:
    	  data[k] = [data[2*k+2][0],data[2*k+2][1]]
      k += 1
# a_k の値を x に更新
def update(k, x):
  firstk = k
  k += N0-1 #この時のk : セグ木上の最下段のidx
  data[k][0] = x
  while k >= 0:
#    print('最初はkは',firstk, 'でしたが今は', k, x, k+N0-1)
    k = (k - 1) // 2
    left = data[2*k+1][0]
    right = data[2*k+2][0]
    if left <= right: #左側が小さければ親ノードに左に入っているidxを送る
      data[k][1] = data[2*k+1][1]
    else: data[k][1] = data[2*k+2][1] #右側が小さかったら
    data[k][0] = min(left,right)
    #右隣のノードと比べて、上のノードに最小値を返す？
# 区間[l, r)の最小値
def query(l, r):
  L = l + N0; R = r + N0
  s = INF
  minidx = 0
  while L < R:
    if R & 1:
      R -= 1
      if data[R-1][0]<s:
        minidx = data[R-1][1]
        s = data[R-1][0]

    if L & 1:
      if data[L-1][0]<s:
        minidx = data[L-1][1]
        s = data[L-1][0]
      L += 1
    L >>= 1; R >>= 1
  return s, minidx
#SegTreeおわり

#もう一個セグ木をつくる（力技）
data2 = [[INF,0] for _ in range(2*N0)]
#各ノードにおける最小値のidxの初期値を格納
for i in range(1, bitlen+1): #(0は除き)1,2,3段目に行う iは段数を表す
  for j in range(0,2**i):
    #一番左は0のまま、残りはidxを変える
    #i段目の左端のidxは2**i-1
    data2[2**i-1 + j][1] = (2**(bitlen-i))*j
#receive arr and initialize segtree
#not necessarily needed
def segfy_(arr):
  i = 0
  for val in arr: #update lowest
    data2[i+N0-1][0] = val
    i += 1
  #i is row number
  for i in range(bitlen-1, -1, -1):
    k = 2**i - 1 #idx
    for j in range(0,2**i):
      if data2[2*k+1][0]<=data2[2*k+2][0]:
    	  data2[k] = [data2[2*k+1][0],data2[2*k+1][1]]
      else:
    	  data2[k] = [data2[2*k+2][0],data2[2*k+2][1]]
      k += 1
# a_k の値を x に更新
def update_(k, x):
  firstk = k
  k += N0-1 #この時のk : セグ木上の最下段のidx
  data2[k][0] = x
  while k >= 0:
#    print('最初はkは',firstk, 'でしたが今は', k, x, k+N0-1)
    k = (k - 1) // 2
    left = data2[2*k+1][0]
    right = data2[2*k+2][0]
    if left <= right: #左側が小さければ親ノードに左に入っているidxを送る
      data2[k][1] = data2[2*k+1][1]
    else: data2[k][1] = data2[2*k+2][1] #右側が小さかったら
    data2[k][0] = min(left,right)
    #右隣のノードと比べて、上のノードに最小値を返す？
# 区間[l, r)の最小値
def query_(l, r):
  L = l + N0; R = r + N0
  s = INF
  minidx = 0
  while L < R:
    if R & 1:
      R -= 1
      if data2[R-1][0]<s:
        minidx = data2[R-1][1]
        s = data2[R-1][0]

    if L & 1:
      if data2[L-1][0]<s:
        minidx = data2[L-1][1]
        s = data2[L-1][0]
      L += 1
    L >>= 1; R >>= 1
  return s, minidx
#SegTree_おわり

aforseg =[]
aforseg_ =[]
for a, i in As:
  aforseg.append((N-1-i)*D+a)
  aforseg_.append(i*D+a)

segfy(aforseg)
segfy_(aforseg_)
#print(data)
#print(data2)

#print(cummin_left)
#print(cummin_right)
#[(cost, idx, adjidx), ...]
edge_candidates = []

for a, o_idx in As_costdescending: #o_idx:降順にする前のidx
  if o_idx == 0: #右だけを見る
    rightmin, rightmin_oidx = query_(1,N) #[L,r)
    edge_candidates.append((abs(o_idx-rightmin_oidx)*D+a+rightmin-rightmin_oidx*D, o_idx, rightmin_oidx))
  elif o_idx == N-1: #左だけを見る
    leftmin, leftmin_oidx = query(0, N-1) #[L,r)
    edge_candidates.append((abs(o_idx-leftmin_oidx)*D+a+leftmin-(N-1-leftmin_oidx)*D, o_idx, leftmin_oidx))
  else:
    rightmin, rightmin_oidx = query_(o_idx+1,N) #[L,r)
    edge_candidates.append((abs(o_idx-rightmin_oidx)*D+a+rightmin-rightmin_oidx*D, o_idx, rightmin_oidx))
    leftmin, leftmin_oidx = query(0, o_idx) #[L,r)
    edge_candidates.append((abs(o_idx-leftmin_oidx)*D+a+leftmin-(N-1-leftmin_oidx)*D, o_idx, leftmin_oidx))
  update(o_idx,INF)
  update_(o_idx,INF)

heapq.heapify(edge_candidates)

#上でできた配列に対してクラスカル法を適用して最小全域木（のコスト総和）を求める
#Union-Findを使ったクラスカル法
uf = UnionFind(N)
ans = 0
for _ in range(len(edge_candidates)):
  c, idx, adjidx = heapq.heappop(edge_candidates)
  if uf.Unite(idx, adjidx): ans += c

print(ans)
