Problem p03153 (C++)

Buggy submission (status: Runtime Error):
#include <cstdio>
#include <cstring>

#include <algorithm>
#include <iostream>
#include <set>
#include <string>
#include <vector>

typedef long long llong;

constexpr int kMaxN = 1e5 + 10;

struct Edge {
  int n1, n2;
  llong cost;
};

int costa[kMaxN];
std::vector<Edge> edges;

Edge NewEdge(int n1, int n2, llong costd) {
  Edge e;
  e.n1 = n1;
  e.n2 = n2;
  e.cost = costd * std::abs(n1 - n2) + costa[n1] + costa[n2];
  return e;
}

void MakeEdge(int low, int upp, llong costd) {
  if (upp - low <= 1) {
    return;
  }
  int mid = (low + upp) / 2;
  MakeEdge(low, mid, costd);
  MakeEdge(mid, upp, costd);

  int min1i = -1;
  llong min1 = 0;
  for (int i = low; i < mid; ++i) {
    llong v = costa[i] - i * (costd);
    if (min1i == -1 || v < min1) {
      min1 = v;
      min1i = i;
    }
  }

  int min2i = -1;
  llong min2 = 0;
  for (int i = mid; i < upp; ++i) {
    llong v = costa[i] + i * (costd);
    if (min2i == -1 || v < min2) {
      min2 = v;
      min2i = i;
    }
  }

  for (int i = low; i < mid; ++i) {
    edges.push_back(NewEdge(i, min2i, costd));
  }

  for (int i = mid; i < upp; ++i) {
    edges.push_back(NewEdge(min1i, i, costd));
  }
}

int union_set_id[kMaxN];

int UnionSetGetRoot(int i) {
  if (i != union_set_id[i]) {
    union_set_id[i] = UnionSetGetRoot(union_set_id[i]);
  }
  return union_set_id[i];
}

void UnionSetUnion(int a, int b) {
  a = UnionSetGetRoot(a);
  b = UnionSetGetRoot(b);
  if (a != b) {
    union_set_id[a] = b;
  }
}

bool CompareEdge(Edge const &e1, Edge const &e2) { return e1.cost < e2.cost; }

int main() {
  int n, d;
  scanf("%d %d", &n, &d);

  for (int i = 0; i < n; ++i) {
    scanf("%d", costa + i);
    union_set_id[i] = i;
  }

  MakeEdge(0, n, d);

  // printf("edge count %zd\n", edges.size());

  // for (auto const &edge : edges) {
  //   printf("edge(n1,n2,cost): %d %d %lld\n", edge.n1, edge.n2, edge.cost);
  // }

  std::sort(edges.begin(), edges.end(), CompareEdge);

  llong total = 0;
  int edge_count = 0;
  for (auto const &edge : edges) {
    if (UnionSetGetRoot(edge.n1) != UnionSetGetRoot(edge.n2)) {
      total += edge.cost;
      UnionSetUnion(edge.n1, edge.n2);
      edge_count += 1;
    }
    if (edge_count == n - 1) {
      break;
    }
  }

  printf("%lld\n", total);
  return 0;
}

Fixed submission:
#include <cstdio>
#include <cstring>

#include <algorithm>
#include <iostream>
#include <set>
#include <string>
#include <vector>

typedef long long llong;

constexpr int kMaxN = 2e5 + 10;

struct Edge {
  int n1, n2;
  llong cost;
};

int costa[kMaxN];
std::vector<Edge> edges;

Edge NewEdge(int n1, int n2, llong costd) {
  Edge e;
  e.n1 = n1;
  e.n2 = n2;
  e.cost = costd * std::abs(n1 - n2) + costa[n1] + costa[n2];
  return e;
}

void MakeEdge(int low, int upp, llong costd) {
  if (upp - low <= 1) {
    return;
  }
  int mid = (low + upp) / 2;
  MakeEdge(low, mid, costd);
  MakeEdge(mid, upp, costd);

  int min1i = -1;
  llong min1 = 0;
  for (int i = low; i < mid; ++i) {
    llong v = costa[i] - i * (costd);
    if (min1i == -1 || v < min1) {
      min1 = v;
      min1i = i;
    }
  }

  int min2i = -1;
  llong min2 = 0;
  for (int i = mid; i < upp; ++i) {
    llong v = costa[i] + i * (costd);
    if (min2i == -1 || v < min2) {
      min2 = v;
      min2i = i;
    }
  }

  for (int i = low; i < mid; ++i) {
    edges.push_back(NewEdge(i, min2i, costd));
  }

  for (int i = mid; i < upp; ++i) {
    edges.push_back(NewEdge(min1i, i, costd));
  }
}

int union_set_id[kMaxN];

int UnionSetGetRoot(int i) {
  if (i != union_set_id[i]) {
    union_set_id[i] = UnionSetGetRoot(union_set_id[i]);
  }
  return union_set_id[i];
}

void UnionSetUnion(int a, int b) {
  a = UnionSetGetRoot(a);
  b = UnionSetGetRoot(b);
  if (a != b) {
    union_set_id[a] = b;
  }
}

bool CompareEdge(Edge const &e1, Edge const &e2) { return e1.cost < e2.cost; }

int main() {
  int n, d;
  scanf("%d %d", &n, &d);

  for (int i = 0; i < n; ++i) {
    scanf("%d", costa + i);
    union_set_id[i] = i;
  }

  MakeEdge(0, n, d);

  // printf("edge count %zd\n", edges.size());

  // for (auto const &edge : edges) {
  //   printf("edge(n1,n2,cost): %d %d %lld\n", edge.n1, edge.n2, edge.cost);
  // }

  std::sort(edges.begin(), edges.end(), CompareEdge);

  llong total = 0;
  int edge_count = 0;
  for (auto const &edge : edges) {
    if (UnionSetGetRoot(edge.n1) != UnionSetGetRoot(edge.n2)) {
      total += edge.cost;
      UnionSetUnion(edge.n1, edge.n2);
      edge_count += 1;
    }
    if (edge_count == n - 1) {
      break;
    }
  }

  printf("%lld\n", total);
  return 0;
}