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: Time Limit Exceeded)

#include <bits/stdc++.h>
using namespace std;

#define ll long long
#define N 200010
#define INF 0x3f3f3f3f3f3f3f3f
int n, d, a[N];

struct SEG
{
	struct node
	{
		int pos; ll Min;
		node() {} 
		node(int pos, ll Min) : pos(pos), Min(Min) {}
		void init() { pos = -1, Min = INF; }
		node operator + (const node &other) const
		{
			node res = node(-1, INF);
			if (Min < other.Min)
			{
				res.Min = Min;
				res.pos = pos;
			}
			else
			{
				res.Min = other.Min;
				res.pos = other.pos;
			}
			return res;
		}
	}a[N << 2], res;
	void build(int id, int l, int r)
	{
		a[id].init();
		if (l == r) 
		{
			a[id].pos = l;
			return;
		}
		int mid = (l + r) >> 1;
		build(id << 1, l, mid);
		build(id << 1 | 1, mid + 1, r);
	}
	void update(int id, int l, int r, int pos, ll val)
	{
		if (l == r)
		{
			a[id].Min = val;
			return;
		}
		int mid = (l + r) >> 1;
		if (pos <= mid) update(id << 1, l, mid, pos, val);
		else update(id << 1 | 1, mid + 1, r, pos, val);
		a[id] = a[id << 1] + a[id << 1 | 1];
	}
	void query(int id, int l, int r, int ql, int qr)
	{
		if (qr < ql) return;
		//printf("%d %d %d %d\n", l, r, ql, qr);
		if (l >= ql && r <= qr) 
		{
			res = res + a[id];
			return;
		}
		int mid = (l + r) >> 1;
		if (ql <= mid) query(id << 1, l, mid, ql, qr);
		if (qr > mid) query(id << 1 | 1, mid + 1, r, ql, qr);
	}
}seg[2];

int pre[N];
int find(int x) { return pre[x] == 0 ? x : pre[x] = find(pre[x]); }

struct node
{
	ll v; int x, y;
	node() {}
	node (int x, int y, ll v) : x(x), y(y), v(v) {}
	bool operator < (const node &other) const { return v > other.v; }
};

priority_queue <node> pq;
void add(int x)
{
	for (int i = 0; i < 2; ++i) seg[i].res.init();
	seg[0].query(1, 1, n, 1, x - 1);
	seg[1].query(1, 1, n, x + 1, n);
	if (seg[0].res.Min == INF && seg[1].res.Min == INF) return; 
	ll tmpl = 1ll * a[x] + 1ll * x * d + seg[0].res.Min;
	ll tmpr = 1ll * a[x] - 1ll * x * d + seg[1].res.Min;
	if (tmpl < tmpr) pq.push(node(x, seg[0].res.pos, tmpl));
	else pq.push(node(x, seg[1].res.pos, tmpr)); 
}

int main()
{
	while (scanf("%d%d", &n, &d) != EOF)
	{
		for (int i = 1; i <= n; ++i) scanf("%d", a + i);
		for (int i = 0; i < 2; ++i) seg[i].build(1, 1, n);
		for (int i = 1; i <= n; ++i)
		{
			seg[0].update(1, 1, n, i, 1ll * a[i] - 1ll * i * d);
			seg[1].update(1, 1, n, i, 1ll * a[i] + 1ll * i * d);
		}
		memset(pre, 0, sizeof pre);
		ll res = 0; 
		seg[1].res.init();
		seg[1].query(1, 1, n, 2, n);
		while (!pq.empty()) pq.pop();
		pq.push(node(1, seg[1].res.pos, 1ll * a[1] - d + seg[1].res.Min));
		seg[0].update(1, 1, n, 1, INF);
		seg[1].update(1, 1, n, 1, INF);
		int cnt = 1;
		while (cnt < n)
		{
			node top = pq.top(); pq.pop();
			int fx = find(top.x), fy = find(top.y);
			//printf("%d %d %lld\n", top.x, top.y, top.v);
			if (fx != fy)
			{
				res += top.v;
				pre[fx] = fy;
				++cnt;
				seg[0].update(1, 1, n, top.y, INF);
				seg[1].update(1, 1, n, top.y, INF);
				add(top.y);
			}
			add(top.x); 
		}
		printf("%lld\n", res);
	}
	return 0;
}