import sys
stdin = sys.stdin
 
sys.setrecursionlimit(10**5) 
 
def li(): return map(int, stdin.readline().split())
def li_(): return map(lambda x: int(x)-1, stdin.readline().split())
def lf(): return map(float, stdin.readline().split())
def ls(): return stdin.readline().split()
def ns(): return stdin.readline().rstrip()
def lc(): return list(ns())
def ni(): return int(stdin.readline())
def nf(): return float(stdin.readline())

# RMQ (セグメント木)
class SegmentTree:
    def __init__(self, n, func, default):
        self.n = pow(2, (n-1).bit_length())
        self.func = func
        self.default = default
        
        self.segtree = [default for _ in range(2*self.n-1)]
        
    def update(self, idx, value):
        idx += (self.n-1)
        self.segtree[idx] = value
        while idx > 0:
            idx = (idx-1) // 2
            self.segtree[idx] = self.func(self.segtree[2*idx+1],
                                          self.segtree[2*idx+2])
            
    def query(self, a, b, idx, l, r):
        if r <= a or b <= l:
            return self.default
        
        elif a <= l and r <= b:
            return self.segtree[idx]

        else:
            return self.func(self.query(a,b,2*idx+1,l,(l+r)//2),
                             self.query(a,b,2*idx+2,(l+r)//2,r))
    
    def between(self, a, b):
        return self.query(a,b,0,0,self.n)
    
    
    def reset(self):
        self.segtree = [self.default]*(2*self.n-1)
        
        
    def inarray(self, arr):
        for i, ai in enumerate(arr):
            idx = i + (self.n-1)
            self.update(idx, ai)
    
# クラスカル法
class UnionFind:
    def __init__(self, node:int) -> None:
        self.n = node
        self.par = [i for i in range(self.n)]
        self.rank = [0 for i in range(self.n)]
        
    def find(self, x:int) -> int:
        if x == self.par[x]:
            return x
        else:
            self.par[x] = self.find(self.par[x])
            return self.par[x]
        
    def unite(self, x:int, y:int) -> bool:
        if self.isSame(x,y):
            #print("x and y has already united")
            return False
        
        rx = self.find(x)
        ry = self.find(y)
        
        if self.rank[rx] < self.rank[ry]:
            self.par[rx] = self.par[ry]
        else:
            self.par[ry] = self.par[rx]
            
            if self.rank[rx] == self.rank[ry]:
                self.rank[rx] += 1
                
        return True
                
    
    def isSame(self, x:int, y:int) -> bool:
        return self.find(x) == self.find(y)
    
    
# edgesは(cost, prev_node, nex_node)をE本格納しているリスト
def kruskal(edges: list, node_num: int) -> int:
    edges.sort(key=lambda x:x[0])
    
    uf = UnionFind(node_num)
    rem = node_num-1
    ans = 0
    for cost, prev, nex in edges:
        if uf.find(prev) != uf.find(nex):           
            uf.unite(prev, nex)
            ans += cost
            rem -= 1
            
        if rem == 0:
            break
        
    return ans

# セグメント木の判定関数
def segfunc(a:list, b:list):
    if a[0] > b[0]:
        return b
    else:
        return a
    

# 入力
n,d = li()
a = list(li())

INFP = [float("inf"), -1]


# 都市番号ラベリング, 規模順にソート
scale_idx = [(ai, i) for i,ai in enumerate(a)]
scale_idx.sort()


# 左を見るセグメント木
segleft = SegmentTree(n, segfunc, INFP)

# 右を見るセグメント木
segright = SegmentTree(n, segfunc, INFP)


edges = []

# 規模順に実行
for scale, idx in scale_idx:
    
    # 左側最小を取得
    scj, idxj = segleft.between(0, idx)
    if [scj, idxj] != INFP:
        cost = scj + idx*d + scale
        edges.append([cost, idx, idxj])
    
    # 右側最小を取得
    scj, idxj = segright.between(idx+1, n)
    if [scj, idxj] != INFP:
        cost = scj - idx*d + scale
        edges.append([cost, idx, idxj])
    
    # セグメント木アップデート
    segleft.update(idx, [scale - idx*d, idx])
    segright.update(idx, [scale + idx*d, idx])
    

    

# 集めた辺でクラスカル法
ans = kruskal(edges, n)
print(ans)