Problem:
Score : 600 points

Problem 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.

Constraints

1 \leq N \leq 2 \times 10^5

1 \leq D \leq 10^9

1 \leq A_{i} \leq 10^9

A_{i} and D are integers.

Input

Input is given from Standard Input in the following format:

N D
A_1 A_2 ... A_N

Output

Print the minimum possible total cost.

Sample Input 1

3 1
1 100 1

Sample Output 1

106

This cost can be achieved by, for example, building roads connecting City 1, 2 and City 1, 3.

Sample Input 2

3 1000
1 100 1

Sample Output 2

2202

Sample Input 3

6 14
25 171 7 1 17 162

Sample Output 3

497

Sample Input 4

12 5
43 94 27 3 69 99 56 25 8 15 46 8

Sample Output 4

658

Solution in C++14 (GCC 5.4.1) (judge verdict: Accepted)

#include <iostream>
#include <algorithm>
#include <string>
#include <vector>
#include <cmath>
#include <map>
#include <queue>
#include <iomanip>
#include <climits>
#define MOD 1000000007
typedef long long ll;
using namespace std;

#define INF LLONG_MAX
class SegmentTree{
public:

  int n;
  vector<pair<ll,int>> tree;

  SegmentTree(int size){
    n=1;
    while(n<size) n*=2;

    tree.resize(2*n-1,make_pair(INF,-1));
    for(int i=n-1;i<2*n-1;i++) tree[i].second=i-(n-1);
  }

  /*SegmentTree(vector<int> v){
    int vSize=v.size();
    n=1;
    while(n<vSize) n*=2;

    tree.resize(2*n-1,INF);

    for(int i=0;i<vSize;i++) tree[i+n-1]=v[i];
    for(int i=n-2;i>=0;i--) tree[i]=min(tree[2*i+1],tree[2*i+2]);
  }*/

  void update(int index,ll value){
    index+=n-1;

    tree[index].first=value;
    while(index>0){
      index=(index-1)/2;
      if(tree[2*index+1].first<tree[2*index+2].first) tree[index]=tree[2*index+1];
      else tree[index]=tree[2*index+2];
    }
  }

  pair<ll,int> getMin(int a,int b,int k,int l,int r){
    if(r<0) r=n;

    if(r<=a||b<=l) return make_pair(INF,-1);
    else if(a<=l&&r<=b) return tree[k];
    else{
      pair<ll,int> lval=getMin(a,b,2*k+1,l,(l+r)/2);
      pair<ll,int> rval=getMin(a,b,2*k+2,(l+r)/2,r);
      if(lval.first<rval.first) return lval;
      else return rval;
    }
  }
};

class DisjointSet{
public:
  vector<int> rank,p;

  DisjointSet() {}
  DisjointSet(int size){
    rank.resize(size,0);
    p.resize(size,0);
    for(int i=0;i<size;i++) makeSet(i);
  }

  void makeSet(int x){
    p[x]=x;
    rank[x]=0;
  }

  bool same(int x,int y){
    return findSet(x)==findSet(y);
  }

  void unite(int x,int y){
    link(findSet(x),findSet(y));
  }

  void link(int x,int y){
    if(rank[x]<rank[y]){
      p[y]=x;
    }else{
      p[x]=y;
      if(rank[x]==rank[y]){
        rank[y]++;
      }
    }
  }

  int findSet(int x){
    if(x!=p[x]){
      p[x]=findSet(p[x]);
    }
    return p[x];
  }
};

class Edge{
public:
  int source,target;
  ll cost;
  Edge(int source=0,int target=0,ll cost=0):
  source(source),target(target),cost(cost){}
  bool operator < (const Edge &e) const{
    return cost < e.cost;
  }
};

ll kruskal(int N,vector<Edge> edges){
  ll totalCost=0;
  sort(edges.begin(),edges.end());
  DisjointSet dset=DisjointSet(N+1);

  for(int i=0;i<N;i++) dset.makeSet(i);

  int source,target;
  for(int i=0;i<edges.size();i++){
    Edge e=edges[i];
    if(!dset.same(e.source,e.target)){
      // MST.push_back(e);
      totalCost+=e.cost;
      //cout<<totalCost<<endl;
      dset.unite(e.source,e.target);
    }
  }
  return totalCost;
}

int main(){
  int n;
  ll d;
  cin>>n>>d;
  vector<pair<ll,int>> a(n+1);
  SegmentTree left(n+1);
  SegmentTree right(n+1);
  for(int i=0;i<n;i++){
    ll x;
    cin>>x;
    a[i]=make_pair(x,i);
    left.update(i,a[i].first-d*i);
    right.update(i,a[i].first+d*i);
  }
  sort(a.begin(),a.end());
  reverse(a.begin(),a.end());

  vector<Edge> edges;
  for(int i=0;i<n;i++){
    int pos=a[i].second;
    pair<ll,int> mil=left.getMin(0,pos,0,0,-1);
    pair<ll,int> mir=right.getMin(pos+1,n,0,0,-1);
    if(mil.second!=-1){
      edges.push_back(Edge(pos,mil.second,a[i].first+d*pos+mil.first));
    }
    if(mir.second!=-1){
      edges.push_back(Edge(pos,mir.second,a[i].first-d*pos+mir.first));
    }
    left.update(pos,1ll<<60);
    right.update(pos,1ll<<60);
  }

  cout<<kruskal(n,edges)<<endl;


  return 0;
}