output_description: Print the minimum possible total cost.
  
  * * *
input_description: Input is given from Standard Input in the following format:
  
      
      
      N D
      A_1 A_2 ... A_N
attempt: ###template###
  import sys
  def input(): return sys.stdin.readline().rstrip()
  from collections import defaultdict, Counter
  from itertools import product, groupby, count, permutations, combinations
  from math import pi, sqrt, ceil, floor
  from collections import deque
  from bisect import bisect, bisect_left, bisect_right
  from string import ascii_lowercase
  import heapq
  INF = float("inf")
  sys.setrecursionlimit(10**7)
  # 4近傍（右, 下, 左, 上）
  dy = [0, -1, 0, 1]
  dx = [1, 0, -1, 0]
  def inside(y: int, x: int, H: int, W: int) -> bool: return 0 <= y < H and 0 <= x < W
  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（新しい集合の根）とする
      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
  
    # 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はやめて、累積最小値を使う
  cummin_left = [0] * N
  cummin_right = [0] * N
  
  tmpmin = INF
  tmpminidx = -1
  for i in range(0, N-1): #leftなので、0~N-2を更新
    if (N-i)*D+As[i][0] <= tmpmin:
      tmpmin = (N-i)D+As[i][0]
      tmpminidx = i
    cummin_left[i] = tmpminidx
  
  tmpmin = INF
  tmpminidx = -1
  for i in range(N-1, 0, -1): #rightなので、N-1~1を更新
  #  print(i+As[i][0])
    if i*D+As[i][0] <= tmpmin:
      tmpmin = i*D+As[i][0]
      tmpminidx = i
    cummin_right[i] = tmpminidx
  
  #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_oidx = cummin_right[1]
      edge_candidates.append((abs(o_idx-rightmin_oidx)*D+a+As[rightmin_oidx][0], o_idx, rightmin_oidx))
    elif o_idx == N-1: #左だけを見る
      leftmin_oidx = cummin_left[N-2]
      edge_candidates.append((abs(o_idx-leftmin_oidx)*D+a+As[leftmin_oidx][0], o_idx, leftmin_oidx))
    else:
      leftmin_oidx = cummin_left[o_idx-1]
  #    print('+0:', o_idx)
  #    print('+1:', o_idx+1, cummin_right[o_idx+1])
      rightmin_oidx = cummin_right[o_idx+1]
      edge_candidates.append((abs(o_idx-leftmin_oidx)*D+a+As[leftmin_oidx][0], o_idx, leftmin_oidx))
      edge_candidates.append((abs(o_idx-rightmin_oidx)*D+a+As[rightmin_oidx][0], o_idx, rightmin_oidx))
  
  
  heapq.heapify(edge_candidates)
  
  #上でできた配列に対してクラスカル法を適用して最小全域木（のコスト総和）を求める
  #Union-Findを使ったクラスカル法
  uf = UnionFind(N)
  ans = 0
  while edge_candidates:
    c, idx, adjidx = heapq.heappop(edge_candidates)
    if not uf.isSameGroup(idx, adjidx):
      ans += c
      uf.Unite(idx, adjidx)
  
  print(ans)
  
  
  
  
problem_description: Statement
  
  There are N cities in Republic of AtCoder. The size of the i-th city is A_{i}.
  Takahashi would like to build N-1 bidirectional roads connecting two cities so
  that any city can be reached from any other city by using these roads.
  
  Assume that the cost of building a road connecting the i-th city and the j-th
  city is |i-j| \times D + A_{i} + A_{j}. For Takahashi, find the minimum
  possible total cost to achieve the objective.
samples: [{"input": "3 1\n    1 100 1", "output": "106\n    \n\nThis cost can be achieved by, for example, building roads connecting City 1, 2\nand City 1, 3.\n\n* * *"}, {"input": "3 1000\n    1 100 1", "output": "2202\n    \n\n* * *"}, {"input": "6 14\n    25 171 7 1 17 162", "output": "497\n    \n\n* * *"}, {"input": "12 5\n    43 94 27 3 69 99 56 25 8 15 46 8", "output": "658"}]