Problem p03153 (C++)

Buggy submission (status: Runtime Error):
#include <algorithm>
#include <iostream>
#include <vector>
using namespace std;
template <class T> inline bool chmax(T &a, T b) {
  if (a < b) {
    a = b;
    return 1;
  }
  return 0;
}
template <class T> inline bool chmin(T &a, T b) {
  if (a > b) {
    a = b;
    return 1;
  }
  return 0;
}

// RMQ
template <class Monoid> struct RMQ {
  const Monoid INF;
  int SIZE_R;
  vector<pair<Monoid, int>> dat;

  RMQ(int n, const Monoid &inf) : INF(inf) { init(n); }
  void init(int n) {
    SIZE_R = 1;
    while (SIZE_R < n)
      SIZE_R *= 2;
    dat.assign(SIZE_R * 2, pair<Monoid, int>(INF, -1));
  }

  /* set, a is 0-indexed */
  void set(int a, const Monoid &v) { dat[a + SIZE_R] = make_pair(v, a); }
  void build() {
    for (int k = SIZE_R - 1; k > 0; --k) {
      dat[k] = min(dat[k * 2], dat[k * 2 + 1]);
    }
  }

  /* update, a is 0-indexed */
  void update(int a, const Monoid &v) {
    int k = a + SIZE_R;
    dat[k] = make_pair(v, a);
    while (k >>= 1)
      dat[k] = min(dat[k * 2], dat[k * 2 + 1]);
  }

  /* get {min-value, min-index}, a and b are 0-indexed */
  pair<Monoid, int> get(int a, int b) {
    pair<Monoid, int> vleft = make_pair(INF, -1), vright = make_pair(INF, -1);
    for (int left = a + SIZE_R, right = b + SIZE_R; left < right;
         left >>= 1, right >>= 1) {
      if (left & 1)
        vleft = min(vleft, dat[left++]);
      if (right & 1)
        vright = min(dat[--right], vright);
    }
    return min(vleft, vright);
  }
  inline Monoid operator[](int a) { return dat[a + SIZE_R].first; }

  /* debug */
  void print() {
    for (int i = 0; i < SIZE_R; ++i) {
      Monoid val = (*this)[i];
      if (val < INF)
        cout << val;
      else
        cout << "INF";
      if (i != SIZE_R - 1)
        cout << ",";
    }
    cout << endl;
  }
};

// Union-Find
struct UnionFind {
  vector<int> par;

  UnionFind(int n) : par(n, -1) {}
  void init(int n) { par.assign(n, -1); }

  int root(int x) {
    if (par[x] < 0)
      return x;
    else
      return par[x] = root(par[x]);
  }

  bool issame(int x, int y) { return root(x) == root(y); }

  bool merge(int x, int y) {
    x = root(x);
    y = root(y);
    if (x == y)
      return false;
    if (par[x] > par[y])
      swap(x, y); // merge technique
    par[x] += par[y];
    par[y] = x;
    return true;
  }

  int size(int x) { return -par[root(x)]; }
};

using pint = pair<int, int>;
using Edge = pair<long long, pint>;

// 入力
int N;
long long D;
vector<pair<long long, int>> A;

int main() {
  cin >> N >> D;
  A.resize(N);
  RMQ<long long> left(N, 1LL << 60), right(N, 1LL << 60);
  for (int i = 0; i < N; ++i) {
    long long a;
    cin >> a;
    A[i] = make_pair(a, i);
    left.set(i, A[i].first - D * i);
    right.set(i, A[i].first + D * i);
  }
  left.build(), right.build();
  sort(A.begin(), A.end(), greater<pair<long long, int>>());

  // A[v] が大きい法から順に
  vector<Edge> edges;
  for (int i = 0; i < N; ++i) {
    int p = A[i].second;
    auto le = left.get(0, p);
    auto ri = right.get(p + 1, N);
    edges.push_back(Edge(A[i].first + D * p + le.first, pint(p, le.second)));
    edges.push_back(Edge(A[i].first - D * p + ri.first, pint(p, ri.second)));
    left.update(p, 1LL << 60);
    right.update(p, 1LL << 60);
  }

  // Kruskal
  UnionFind uf(N);
  sort(edges.begin(), edges.end());
  long long res = 0;
  for (auto e : edges) {
    long long w = e.first;
    int u = e.second.first, v = e.second.second;
    if (uf.issame(u, v))
      continue;
    res += w;
    uf.merge(u, v);
  }
  cout << res << endl;
}

Fixed submission:
#include <algorithm>
#include <iostream>
#include <vector>
using namespace std;
template <class T> inline bool chmax(T &a, T b) {
  if (a < b) {
    a = b;
    return 1;
  }
  return 0;
}
template <class T> inline bool chmin(T &a, T b) {
  if (a > b) {
    a = b;
    return 1;
  }
  return 0;
}

// RMQ
template <class Monoid> struct RMQ {
  const Monoid INF;
  int SIZE_R;
  vector<pair<Monoid, int>> dat;

  RMQ(int n, const Monoid &inf) : INF(inf) { init(n); }
  void init(int n) {
    SIZE_R = 1;
    while (SIZE_R < n)
      SIZE_R *= 2;
    dat.assign(SIZE_R * 2, pair<Monoid, int>(INF, -1));
  }

  /* set, a is 0-indexed */
  void set(int a, const Monoid &v) { dat[a + SIZE_R] = make_pair(v, a); }
  void build() {
    for (int k = SIZE_R - 1; k > 0; --k) {
      dat[k] = min(dat[k * 2], dat[k * 2 + 1]);
    }
  }

  /* update, a is 0-indexed */
  void update(int a, const Monoid &v) {
    int k = a + SIZE_R;
    dat[k] = make_pair(v, a);
    while (k >>= 1)
      dat[k] = min(dat[k * 2], dat[k * 2 + 1]);
  }

  /* get {min-value, min-index}, a and b are 0-indexed */
  pair<Monoid, int> get(int a, int b) {
    pair<Monoid, int> vleft = make_pair(INF, -1), vright = make_pair(INF, -1);
    for (int left = a + SIZE_R, right = b + SIZE_R; left < right;
         left >>= 1, right >>= 1) {
      if (left & 1)
        vleft = min(vleft, dat[left++]);
      if (right & 1)
        vright = min(dat[--right], vright);
    }
    return min(vleft, vright);
  }
  inline Monoid operator[](int a) { return dat[a + SIZE_R].first; }

  /* debug */
  void print() {
    for (int i = 0; i < SIZE_R; ++i) {
      Monoid val = (*this)[i];
      if (val < INF)
        cout << val;
      else
        cout << "INF";
      if (i != SIZE_R - 1)
        cout << ",";
    }
    cout << endl;
  }
};

// Union-Find
struct UnionFind {
  vector<int> par;

  UnionFind(int n) : par(n, -1) {}
  void init(int n) { par.assign(n, -1); }

  int root(int x) {
    if (par[x] < 0)
      return x;
    else
      return par[x] = root(par[x]);
  }

  bool issame(int x, int y) { return root(x) == root(y); }

  bool merge(int x, int y) {
    x = root(x);
    y = root(y);
    if (x == y)
      return false;
    if (par[x] > par[y])
      swap(x, y); // merge technique
    par[x] += par[y];
    par[y] = x;
    return true;
  }

  int size(int x) { return -par[root(x)]; }
};

using pint = pair<int, int>;
using Edge = pair<long long, pint>;

// 入力
int N;
long long D;
vector<pair<long long, int>> A;

int main() {
  cin >> N >> D;
  A.resize(N);
  RMQ<long long> left(N, 1LL << 60), right(N, 1LL << 60);
  for (int i = 0; i < N; ++i) {
    long long a;
    cin >> a;
    A[i] = make_pair(a, i);
    left.set(i, A[i].first - D * i);
    right.set(i, A[i].first + D * i);
  }
  left.build(), right.build();
  sort(A.begin(), A.end(), greater<pair<long long, int>>());

  // A[v] が大きい法から順に
  vector<Edge> edges;
  for (int i = 0; i < N; ++i) {
    int p = A[i].second;
    auto le = left.get(0, p);
    auto ri = right.get(p + 1, N);
    if (le.second != -1)
      edges.push_back(Edge(A[i].first + D * p + le.first, pint(p, le.second)));
    if (ri.second != -1)
      edges.push_back(Edge(A[i].first - D * p + ri.first, pint(p, ri.second)));
    left.update(p, 1LL << 60);
    right.update(p, 1LL << 60);
  }

  // Kruskal
  UnionFind uf(N);
  sort(edges.begin(), edges.end());
  long long res = 0;
  for (auto e : edges) {
    long long w = e.first;
    int u = e.second.first, v = e.second.second;
    if (uf.issame(u, v))
      continue;
    res += w;
    uf.merge(u, v);
  }
  cout << res << endl;
}