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# (Mono 4.6.2.0) (judge verdict: Accepted)

using System;
using System.Collections;
using System.Collections.Generic;
using System.IO;
using System.Linq;
using System.Numerics;
using System.Text;
using System.Threading.Tasks;

namespace AtCorder
{
	public class Program
	{
		static void Main(string[] args)
		{
			var cin = new Scanner2();
			int n = cin.Int();
			long d = cin.Long();
			long[] a = cin.ArrayLong(n);
			int[] ai = Enumerable.Range(0, n).OrderBy(x => a[x]).ToArray();
			var RSeg = new SegmentTree<Tuple<long, int>>(n, new Tuple<long, int>(long.MaxValue, -1), Merge);
			var LSeg = new SegmentTree<Tuple<long, int>>(n, new Tuple<long, int>(long.MaxValue, -1), Merge);

			var edge = new List<Edge>();
			for (int i = 0; i < n; i++) {
				int pos = ai[i];
				var cost = a[pos];

				var r = RSeg.Query(pos, n).Item2;
				if (r != -1) {
					edge.Add(new Edge(pos, r, cost + a[r] + d * Math.Abs(pos - r)));
				}

				var l = LSeg.Query(0, pos + 1).Item2;
				if (l != -1) {
					edge.Add(new Edge(pos, l, cost + a[l] + d * Math.Abs(pos - l)));
				}

				RSeg.Update(pos, new Tuple<long, int>(cost + d * pos, pos));
				LSeg.Update(pos, new Tuple<long, int>(cost - d * pos, pos));
			}

			var uf = new UnionFindTree(n);
			long ans = 0;
			var edge2 = edge.OrderBy(x => x.Cost).ToArray();
			foreach (var e in edge2) {
				if (uf.IsUnited(e.From, e.To) == false) {
					uf.TryUnite(e.From, e.To);
					ans += e.Cost;
				}
			}

			Console.WriteLine(ans);
		}

		public static Tuple<long, int> Merge(Tuple<long, int> a, Tuple<long, int> b)
		{
			return a.Item1 < b.Item1 ? a : b;
		}
	}

	public struct Edge
	{
		public int From;
		public int To;
		public long Cost;

		public Edge(int from, int to, long cost)
		{
			From = from;
			To = to;
			Cost = cost;
		}
	}

	public class SegmentTree<T>
	{
		private readonly int n_;
		private readonly T max_;
		private readonly T[] tree_;
		private readonly Func<T, T, T> merge_;

		public int Count { get; }
		public int Height { get; }
		public T Top => tree_[1];

		public SegmentTree(int count, T max, Func<T, T, T> merge)
		{
			merge_ = merge;
			max_ = max;

			Count = count;
			n_ = 1;
			Height = 1;
			while (n_ < count) {
				++Height;
				n_ <<= 1;
			}

			tree_ = new T[n_ * 2];
			for (int i = 0; i < tree_.Length; i++) {
				tree_[i] = max;
			}
		}

		public SegmentTree(T[] src, T max, Func<T, T, T> merge)
			: this(src.Length, max, merge)
		{
			for (int i = 0; i < n_; ++i) {
				tree_[i + n_] = src[i];
			}

			for (int i = n_ - 1; i > 0; --i) {
				tree_[i] = merge_(tree_[i * 2 + 0], tree_[i * 2 + 1]);
			}
		}

		public T this[int index]
		{
			get { return tree_[index + n_]; }
			set { Update(index, value); }
		}

		public void Update(int index, T val)
		{
			if (index >= Count) {
				return;
			}

			index += n_;
			tree_[index] = val;
			index /= 2;
			while (index != 0) {
				tree_[index] = merge_(tree_[index * 2], tree_[index * 2 + 1]);
				index /= 2;
			}
		}

		public T Query(int l, int r)
		{
			if (l > r || r < 0 || l >= Count) {
				return max_;
			}

			l += n_;
			r += n_;
			T minL = max_;
			T minR = max_;
			while (l < r) {
				if (l % 2 != 0) {
					minL = merge_(minL, tree_[l]);
					++l;
				}
				if (r % 2 != 0) {
					--r;
					minR = merge_(tree_[r], minR);
				}

				l /= 2;
				r /= 2;
			}

			return merge_(minL, minR);
		}
	}

	public class UnionFindTree
	{
		private readonly List<int> sizes_;
		private readonly List<int> parents_;

		public int Count { get; private set; }
		public int GroupCount { get; private set; }

		public UnionFindTree(int count)
		{
			parents_ = new List<int>(count);
			sizes_ = new List<int>(count);

			Count = 0;
			GroupCount = 0;

			ExtendSize(count);
		}

		public bool IsUnited(int x, int y)
		{
			int xRoot = Find(x);
			int yRoot = Find(y);

			return xRoot == yRoot;
		}

		public bool TryUnite(int x, int y)
		{
			int xRoot = Find(x);
			int yRoot = Find(y);
			if (yRoot == xRoot) {
				return false;
			}

			int parent = sizes_[xRoot] < sizes_[yRoot] ? yRoot : xRoot;
			int child = sizes_[xRoot] < sizes_[yRoot] ? xRoot : yRoot;

			GroupCount--;
			parents_[child] = parent;
			sizes_[parent] += sizes_[child];

			return true;
		}
		public IEnumerable<int> AllRepresents => parents_.Where(x => x == parents_[x]);
		public int GetSize(int x) => sizes_[Find(x)];

		public int Find(int x)
		{
			while (x != parents_[x]) {
				parents_[x] = parents_[parents_[x]];
				x = parents_[x];
			}

			return x;
		}

		public void ExtendSize(int treeSize)
		{
			if (treeSize <= Count) {
				return;
			}

			parents_.Capacity = treeSize;
			sizes_.Capacity = treeSize;
			while (Count < treeSize) {
				parents_.Add(Count);
				sizes_.Add(1);
				Count++;
				GroupCount++;
			}
		}
	}

	public class Scanner2
	{
		private readonly char[] delimiter_ = new char[] { ' ' };
		private readonly string filePath_;
		private string[] buf_;
		private int index_;
		Func<string> reader_;

		public Scanner2(string file = "")
		{
			if (string.IsNullOrWhiteSpace(file)) {
				reader_ = Console.ReadLine;
			} else {
				filePath_ = file;
				var fs = new StreamReader(file);
				reader_ = fs.ReadLine;
			}
			buf_ = new string[0];
			index_ = 0;
		}

		public string Next()
		{
			if (index_ < buf_.Length) {
				return buf_[index_++];
			}

			string st = reader_();
			while (st == "") {
				st = reader_();
			}

			buf_ = st.Split(delimiter_, StringSplitOptions.RemoveEmptyEntries);
			if (buf_.Length == 0) {
				return Next();
			}

			index_ = 0;
			return buf_[index_++];
		}

		public int Int() => int.Parse(Next());
		public long Long() => long.Parse(Next());
		public double Double() => double.Parse(Next());

		public int[] ArrayInt(int N, int add = 0)
		{
			int[] Array = new int[N];
			for (int i = 0; i < N; i++) {
				Array[i] = Int() + add;
			}
			return Array;
		}

		public long[] ArrayLong(int N, long add = 0)
		{
			long[] Array = new long[N];
			for (int i = 0; i < N; i++) {
				Array[i] = Long() + add;
			}
			return Array;
		}

		public double[] ArrayDouble(int N, double add = 0)
		{
			double[] Array = new double[N];
			for (int i = 0; i < N; i++) {
				Array[i] = Double() + add;
			}
			return Array;
		}

		public void Save(string text)
		{
			if (string.IsNullOrWhiteSpace(filePath_)) {
				return;
			}

			File.WriteAllText(filePath_ + "_output.txt", text);
		}
	}
}