Sunday, July 31, 2016

UVa 11415 - Count the Factorials

Accepted date: 2016-07-31
Run Time: 0.270
Ranking (as of 2016-07-28): 63 out of 397
Language: C++

/*
  UVa 11415 - Count the Factorials

  To build using Visual Studio 2012:
    cl -EHsc -O2 UVa_11415_Count_the_Factorials.cpp
*/

#include <algorithm>
#include <cstdio>
#include <cmath>
#ifdef __ELAPSED_TIME__
#include <ctime>
#endif
using namespace std;

const int n_max = 10000000;
bool not_primes[n_max + 1]; // not_primes[i] is true if i is not a prime
int multiplicities[n_max + 1];

void sieve_of_eratosthenes()
{
  for (int i = 2, e = static_cast<int>(sqrt(static_cast<double>(n_max))); i <= e; i++)
    if (!not_primes[i]) {
      for (int j = i * i; j <= n_max; j += i)
        not_primes[j] = true;
    }
}

int main()
{
#ifdef __ELAPSED_TIME__
  clock_t start = clock();
#endif
  sieve_of_eratosthenes();
  int m = 2;
  for (int count = 0; m <= n_max && count <= n_max; m++) {
    if (!not_primes[m]) {
      for (long long j = m; j <= n_max; j *= m)
        for (long long k = j; k <= n_max; k += j)
          multiplicities[k]++;
    }
    count += multiplicities[m];
    multiplicities[m] = count;
  }
#ifdef DEBUG
  printf("%d: %d\n", m - 1, multiplicities[m - 1]);
#endif
  int t;
  scanf("%d", &t);
  while (t--) {
    int n;
    scanf("%d", &n);
    printf("%d\n", upper_bound(multiplicities, multiplicities + m, n) - multiplicities);
  }
#ifdef __ELAPSED_TIME__
  fprintf(stderr, "elapsed time = %lf sec.\n",
    static_cast<double>(clock() - start) / CLOCKS_PER_SEC);
#endif
  return 0;
}

Friday, July 29, 2016

UVa 157 - Route Finding

Accepted date: 2016-07-28
Run Time: 0.000
Ranking (as of 2016-07-28): 145 out of 492
Language: C++

/*
  UVa 157 - Route Finding

  To build using Visual Studio 2012:
    cl -EHsc -O2 UVa_157_Route_Finding.cpp
*/

#include <iostream>
#include <string>
#include <sstream>
#include <vector>
#include <set>
#include <map>
#include <limits>
#include <cstdio>
using namespace std;

const int infinite = numeric_limits<int>::max();
const int nr_letters = 'z' - 'a' + 1, n_max = nr_letters * nr_letters;

struct edge {
  int v_;
  int w_;
  edge(int v, int w) : v_(v), w_(w) {}
};

vector<edge> edges[n_max];
bool visited[n_max];
int distances[n_max], parents[n_max];

struct distance_comparator {
  bool operator() (int i, int j) const
  {
    return (distances[i] != distances[j]) ? distances[i] < distances[j] : i < j;
  }
};

int dijkstra_shortest_path(int n, int start, int end)
{
  for (int i = 0; i < n; i++)
    visited[i] = false, distances[i] = infinite;
  set<int, distance_comparator> pq; // priority queue
  distances[start] = 0, parents[start] = -1;
  pq.insert(start);
  while(!pq.empty()) {
    int u = *pq.begin();
    pq.erase(pq.begin());
    visited[u] = true;
    if (u == end)
      break;
    int d = distances[u], pw = (u != start) ? d - distances[parents[u]] : -1;
    const vector<edge>& es = edges[u];
    for (size_t i = 0, j = es.size(); i < j; i++) {
      int v = es[i].v_, w = es[i].w_;
      if (w == 3 && (pw == 3 || pw == 0)) // pass through several connections
        w = 0;
      if (!visited[v] && distances[v] > d + w) {
        pq.erase(v); // remove v if it has already been in the queue
        distances[v] = d + w, parents[v] = u;
        pq.insert(v);
      }
    }
  }
  return distances[end];
}

map<pair<char, char>, int> vertices;
map< int, pair<char, char> > stations;

int get_vertex(char cr, char cs)
{
  pair<map<pair<char, char>, int>::iterator, bool> result =
    vertices.insert(make_pair(make_pair(cr, cs), static_cast<int>(vertices.size())));
  if (result.second)
    stations.insert(make_pair(result.first->second, make_pair(cr, cs)));
  return result.first->second;
}

void print_path(int u, int w, char& cr)
{
  pair<int, int> s = stations[u];
  if (parents[u] == -1) {
    cr = s.first;
    printf("%c%c", cr, s.second);
  }
  else {
    print_path(parents[u], distances[u] - distances[parents[u]], cr);
    if (w) {
      if (s.first != cr) {
        cr = s.first;
        printf("=%c%c", cr, s.second);
      }
      else
        putchar(s.second);
    }
  }
}

int main()
{
  string s;
  getline(cin, s);
  istringstream iss(s);
  int nr_routes;
  iss >> nr_routes;
  vertices.clear();
  while (nr_routes--) {
    getline(cin, s);
    const char* p = s.c_str();
    char cr = *p++;
    int u = get_vertex(cr, *++p), su = u, v;
    for (p++; *p; p++) {
      if (*p == '=') { // ...hc=Bg=Cc=Abd...
        int ccr = *++p;
        v = get_vertex(ccr, *++p);
        if (v != su)
          edges[u].push_back(edge(v, 3)), edges[v].push_back(edge(u, 3));
        else
          edges[u].push_back(edge(v, 1)), edges[v].push_back(edge(u, 1));
      }
      else {
        v = get_vertex(cr, *p);
        edges[u].push_back(edge(v, 1)), edges[v].push_back(edge(u, 1));
        u = v;
      }
    }
  }
  int n = static_cast<int>(vertices.size());
  while (getline(cin, s) && s[0] != '#') {
    int start = get_vertex(s[0], s[1]), end = get_vertex(s[2], s[3]);
    int d = dijkstra_shortest_path(n, start, end);
    printf("%3d: ", d);
    char cr;
    print_path(end, -1, cr);
    putchar('\n');
  }
  return 0;
}

Wednesday, July 27, 2016

UVa 1594 - Ducci Sequence

Accepted date: 2016-07-27
Run Time: 0.290
Ranking (as of 2016-07-26): 191 out of 477
Language: C++

/*
  UVa 1594 - Ducci Sequence

  To build using Visual Studio 2012:
    cl -EHsc -O2 UVa_1594_Ducci_Sequence.cpp
*/

#include <set>
#include <cstdio>
#include <cstdlib>
using namespace std;

const int n_max = 15, seq_max = 1024;

struct tuple_ {
  int integers_[n_max];
} tuples[seq_max];

struct tuple_comparator {
  int n_;
  tuple_comparator(int n) : n_(n) {}
  bool operator() (const tuple_* ti, const tuple_* tj) const {
    for (int i = 0; i < n_; i++)
      if (ti->integers_[i] != tj->integers_[i])
        return ti->integers_[i] < tj->integers_[i];
    return false;
  }
};

int main()
{
  int T;
  scanf("%d", &T);
  while (T--) {
    int n;
    scanf("%d", &n);
    bool zero = true;
    for (int i = 0; i < n; i++) {
      scanf("%d", &tuples[0].integers_[i]);
      if (tuples[0].integers_[i])
        zero = false;
    }
    if (!zero) {
      set<tuple_*, tuple_comparator> st(n);
      st.insert(&tuples[0]);
      for (int i = 1; ; i++) {
        zero = true;
        for (int j = 0; j < n; j++)
          if (tuples[i].integers_[j] =
            abs(tuples[i - 1].integers_[j] - tuples[i - 1].integers_[(j + 1) % n]))
            zero = false;
        if (zero)
          break;
#ifdef DEBUG
        for (int j = 0; j < n; j++)
          printf("%d%c", tuples[i].integers_[j], ((j < n - 1) ? ' ' : '\n'));
#endif
        pair<set<tuple_*, tuple_comparator>::iterator, bool> result = st.insert(&tuples[i]);
        if (!result.second)
          break;
      }
    }
    puts((zero) ? "ZERO" : "LOOP");
  }
  return 0;
}

Tuesday, July 26, 2016

UVa 209 - Triangular Vertices

Accepted date: 2016-07-26
Run Time: 0.070
Ranking (as of 2016-07-26): 118 out of 643
Language: C++

/*
  UVa 209 - Triangular Vertices

  To build using Visual Studio 2012:
    cl -EHsc -O2 UVa_209_Triangular_Vertices.cpp
*/

#include <algorithm>
#include <iostream>
#include <string>
#include <sstream>
#include <cstdlib>
#include <cmath>
using namespace std;

const int nr_points_max = 6;

struct point {
  int r_, c_;

bool operator<(const point& p) const {return (r_ != p.r_) ? r_ < p.r_ : c_ < p.c_;}
bool operator==(const point& p) const {return r_ == p.r_ && c_ == p.c_;}
} points[nr_points_max];

void get_point(int n, point& p)
{
  int r = static_cast<int>((sqrt(1.0 + 8.0 * n) - 1.0) / 2.0);
  if (r * (r + 1) / 2 < n)
    r++;
  p.r_ = r;
  p.c_ = n - (r - 1) * r / 2;
}

int get_length(const point& p, const point& q)
{
  if (p.r_ == q.r_)
    return abs(p.c_ - q.c_);
  else if (p.c_ == q.c_)
    return abs(p.r_ - q.r_);
  else if (p.c_ - q.c_ == p.r_ - q.r_)
    return abs(p.r_ - q.r_);
  else
    return -1;
}

bool is_triangle()
{
  int a = get_length(points[0], points[1]), b = get_length(points[1], points[2]),
    c = get_length(points[2], points[0]);
  return a > 0 && a == b && b == c;
}

bool is_parallelogram()
{
  int a = get_length(points[0], points[1]), b = get_length(points[2], points[3]),
    c = get_length(points[0], points[2]), d = get_length(points[1], points[3]);
  return a > 0 && a == b && b == c && c == d;
}

bool is_hexagon()
{
  if (points[0].r_ != points[1].r_)
    return false;
  int a = points[1].c_ - points[0].c_;
  if (points[0].c_ != points[2].c_ || a != points[2].r_ - points[0].r_)
    return false;
  if (points[3].c_ > points[1].c_ &&
    points[3].c_ - points[1].c_ == points[3].r_ - points[1].r_ &&
    points[3].c_ - points[1].c_ == a)
    ;
  else
    return false;
  if (points[4].c_ > points[2].c_ &&
    points[4].c_ - points[2].c_ == points[4].r_ - points[2].r_ &&
    points[4].c_ - points[2].c_ == a)
    ;
  else
    return false;
  if (points[3].c_ != points[5].c_ || a != points[5].r_ - points[3].r_)
    return false;
  if (points[4].r_ != points[5].r_ || points[5].c_ - points[4].c_ != a)
    return false;
  return true;
}

int main()
{
  string s;
  while (getline(cin, s)) {
    istringstream iss(s);
    int p, nr_points = 0;
    for ( ; iss >> p; nr_points++) {
      cout << p << ' ';
      get_point(p, points[nr_points]);
    }
    bool acceptable = false;
    sort(points, points + nr_points);
    int nr_unique = unique(points, points + nr_points) - points;
    if (nr_unique == nr_points && (nr_points == 3 || nr_points == 4 || nr_points == 6)) {
#ifdef DEBUG
      for (int i = 0; i < nr_points; i++)
        cout << '(' << points[i].r_ << ',' << points[i].c_ << ") ";
      cout << endl;
#endif
      if (nr_points == 3) {
        if (acceptable = is_triangle())
          cout << "are the vertices of a triangle\n";
      }
      else if (nr_points == 4) {
        if (acceptable = is_parallelogram())
          cout << "are the vertices of a parallelogram\n";
      }
      else {
        if (acceptable = is_hexagon())
          cout << "are the vertices of a hexagon\n";
      }
    }
    if (!acceptable)
      cout << "are not the vertices of an acceptable figure\n";
  }
  return 0;
}

Sunday, July 24, 2016

UVa 10022 - Delta-wave

Accepted date: 2016-07-24
Run Time: 0.000
Ranking (as of 2016-07-24): 289 out of 556
Language: C++

/*
  UVa 10022 - Delta-wave

  To build using Visual Studio 2012:
    cl -EHsc -O2 UVa_10022_Delta-wave.cpp
*/

#include <algorithm>
#include <cstdio>
#include <cstdlib>
#include <cmath>
using namespace std;

void get_position(int n, int& r, int& c)
{
  r = static_cast<int>(sqrt(static_cast<double>(n)));
  int sr = r * r;
  if (sr < n) {
    c = n - sr;
    r++;
  }
  else {
    c = n - (r - 1) * (r - 1);
  }
}

int main()
{
  int nr_cases;
  scanf("%d", &nr_cases);
  while (nr_cases--) {
    int M, N;
    scanf("%d %d", &M, &N);
    if (M > N)
      swap(M, N);
    int mr, mc, nr, nc;
    get_position(M, mr, mc);
    get_position(N, nr, nc);
#ifdef DEBUG
    printf("M:(%d, %d) N:(%d, %d)\n", mr, mc, nr, nc);
#endif
    int sp = 0;
    for ( ; mr < nr; mr++) {
      if (mc & 1) // mc is odd
        mc++, sp++;
      else if (mc + 2 == nc)
        mc = nc, sp += 2;
      else if (mc + 2 < nc)
        mc += 2, sp += 2;
      else
        sp += 2;
#ifdef DEBUG
    printf("\tM:(%d, %d)\n", mr + 1, mc);
#endif
    }
    sp += abs(nc - mc);
    printf("%d\n", sp);
    if (nr_cases)
      putchar('\n');
  }
  return 0;
}

Tuesday, July 19, 2016

UVa 10883 - Supermean

Accepted date: 2016-07-19
Run Time: 0.050
Ranking (as of 2016-07-19): 30 out of 402
Language: C++11

/*
  UVa 10883 - Supermean

  To build using Visual Studio 2012:
    cl -EHsc -O2 UVa_10883_Supermean.cpp
*/

#include <cstdio>
#include <cmath>

const int n_max = 50000;
double sums_of_log2s[n_max + 1];
  // sums_of_log2s[i] is the sum of log2[i] (i = 1, 2, ..., i)
int numbers[n_max];

double coefficient(int n, int k)
{
  double d = static_cast<double>(-n);
  if (k)
    d += sums_of_log2s[n] - sums_of_log2s[n - k] - sums_of_log2s[k];
  return pow(2.0, d);
}

int main()
{
  double s = 0.0;
  for (int i = 1; i <= n_max; i++) {
    s += log2(static_cast<double>(i));
    sums_of_log2s[i] = s;
  }
  int N;
  scanf("%d", &N);
  for (int cn = 1; cn <= N; cn++) {
    int n;
    scanf("%d", &n);
    double sm = 0.0, d;
    for (int k = 0; k < n; k++) {
      scanf("%lf", &d);
      sm += coefficient(n - 1, k) * d;
    }
    printf("Case #%d: %.3lf\n", cn, sm);
  }
  return 0;
}

Monday, July 11, 2016

UVa 12662 - Good Teacher

Accepted date: 2016-07-11
Run Time: 0.000
Ranking (as of 2016-07-11): 76 out of 403
Language: C++

/*
  UVa 12662 - Good Teacher

  To build using Visual Studio 2012:
    cl -EHsc -O2 UVa_12662_Good_Teacher.cpp
*/

#include <algorithm>
#include <cstdio>
using namespace std;

const int n_max = 100, nr_chars_max = 3;

int positions[n_max];
char names[n_max][nr_chars_max + 1];

int main()
{
  int n;
  scanf("%d", &n);
  int nr_positions = 0;
  for (int p = 1; p <= n; p++) {
    scanf("%s", names[nr_positions]);
    if (names[nr_positions][0] != '?')
      positions[nr_positions++] = p;
  }
  int q;
  scanf("%d", &q);
  while (q--) {
    int p;
    scanf("%d", &p);
    int pi = lower_bound(positions, positions + nr_positions, p) - positions, l, r;
    if (pi == nr_positions) {
      for (r = p - positions[pi - 1]; r; r--)
        printf("right of ");
      printf("%s\n", names[pi - 1]);
    }
    else if (positions[pi] == p)
      printf("%s\n", names[pi]);
    else if (!pi) {
      for (l = positions[pi] - p; l; l--)
        printf("left of ");
      printf("%s\n", names[pi]);
    }
    else {
      r = p - positions[pi - 1], l = positions[pi] - p;
      if (r > l) {
        for ( ; l; l--)
          printf("left of ");
        printf("%s\n", names[pi]);
      }
      else if (r < l) {
        for ( ; r; r--)
          printf("right of ");
        printf("%s\n", names[pi - 1]);
      }
      else
        printf("middle of %s and %s\n", names[pi - 1], names[pi]);
    }
  }
  return 0;
}

Wednesday, July 6, 2016

UVa 12144 - Almost Shortest Path

Accepted date: 2016-07-06
Run Time: 0.030
Ranking (as of 2016-07-06): 25 out of 268
Language: C++

/*
  UVa 12144 - Almost Shortest Path

  To build using Visual Studio 2012:
    cl -EHsc -O2 UVa_12144_Almost_Shortest_Path.cpp
*/

#include <vector>
#include <set>
#include <queue>
#include <utility>
#include <limits>
#include <cstdio>
using namespace std;

const int infinite = numeric_limits<int>::max();
const int N_max = 500;

struct edge {
  int v_;
  int w_;
  bool removed_;
  edge(int v, int w) : v_(v), w_(w), removed_(false) {}
};

vector<edge> edges[N_max];
int distances[N_max];
bool visited[N_max];
vector< pair<int, int> > paths[N_max];

struct distance_comparator {
  bool operator() (int i, int j) const
  {
    return (distances[i] != distances[j]) ? distances[i] < distances[j] : i < j;
  }
};

int shortest_path(int n, int start, int end)
{
  for (int i = 0; i < n; i++)
    visited[i] = false, distances[i] = infinite, paths[i].clear();
  set<int, distance_comparator> pq; // priority queue
  int min_d = -1;
  distances[start] = 0;
  pq.insert(start);
  while(!pq.empty()) {
    int u = *pq.begin();
    pq.erase(pq.begin());
    visited[u] = true;
    int d = distances[u];
#ifdef DEBUG
    printf("%d: %d\n", u, d);
#endif
    if (u == end)
      min_d = d;
    else {
      const vector<edge>& es = edges[u];
      for (int i = 0, j = static_cast<int>(es.size()); i < j; i++) {
        int v = es[i].v_, w = es[i].w_;
        if (!visited[v] && distances[v] > d + w) {
          pq.erase(v); // remove v if it has already been in the queue
          distances[v] = d + w;
          paths[v].clear();
          paths[v].push_back(make_pair(u, i));
#ifdef DEBUG
          printf("\t%d-%d\n", u, v);
#endif
          pq.insert(v);
        }
        else if (distances[v] == d + w) {
          paths[v].push_back(make_pair(u, i));
#ifdef DEBUG
          printf("\t%d-%d\n", u, v);
#endif
        }
      }
    }
  }
  return min_d;
}

void mark_shortest_paths(int n, int end)
{
  for (int i = 0; i < n; i++)
    visited[i] = false;
  queue<int> q;
  visited[end] = true;
  q.push(end);
  while (!q.empty()) {
    int u = q.front();
    q.pop();
    vector< pair<int, int> >& ps = paths[u];
    for (int i = 0, j = static_cast<int>(ps.size()); i < j; i++) {
      int v = ps[i].first;
#ifdef DEBUG
      printf("%d-%d\n", v, edges[v][ps[i].second].v_);
#endif
      edges[v][ps[i].second].removed_ = true;
      if (!visited[v]) {
        visited[v] = true;
        q.push(v);
      }
    }
  }
}

int allmost_shortest_path(int n, int start, int end)
{
  for (int i = 0; i < n; i++)
    visited[i] = false, distances[i] = infinite;
  set<int, distance_comparator> pq; // priority queue
  distances[start] = 0;
  pq.insert(start);
  while(!pq.empty()) {
    int u = *pq.begin();
    pq.erase(pq.begin());
    visited[u] = true;
    int d = distances[u];
    if (u == end)
      return d;
    const vector<edge>& es = edges[u];
    for (size_t i = 0, j = es.size(); i < j; i++) {
      if (es[i].removed_)
        continue;
      int v = es[i].v_, w = es[i].w_;
      if (!visited[v] && distances[v] > d + w) {
        pq.erase(v); // remove v if it has already been in the queue
        distances[v] = d + w;
        pq.insert(v);
      }
    }
  }
  return -1;
}

int main()
{
  while (true) {
    int N, M;
    scanf("%d %d", &N, &M);
    if (!N)
      break;
    for (int i = 0; i < N; i++)
      edges[i].clear();
    int S, D;
    scanf("%d %d", &S, &D);
    while (M--) {
      int U, V, P;
      scanf("%d %d %d", &U, &V, &P);
      edges[U].push_back(edge(V, P));
    }
    int d = shortest_path(N, S, D);
#ifdef DEBUG
    printf("%d\n", d);
#endif
    if (d != -1) {
      mark_shortest_paths(N, D);
      d = allmost_shortest_path(N, S, D);
    }
    printf("%d\n", d);
  }
  return 0;
}

Saturday, July 2, 2016

UVa 1246 - Find Terrorists

Accepted date: 2016-07-02
Run Time: 0.000
Ranking (as of 2016-07-02): 19 out of 405
Language: C++

/*
  UVa 1246 - Find Terrorists

  To build using Visual Studio 2012:
    cl -EHsc -O2 UVa_1246_Find_Terrorists.cpp
*/

#include <algorithm>
#include <cstdio>
#include <cmath>
using namespace std;

const int n_max = 10000, max_nr_divisors = 64;
int nr_divisors[n_max + 1];
bool not_primes[max_nr_divisors + 1]; // not_primes[i] is true if i is not a prime
bool nr_divisors_primes[n_max + 1];

void sieve_of_eratosthenes()
{
  for (int i = 2, e = static_cast<int>(sqrt(static_cast<double>(max_nr_divisors)));
    i <= e; i++)
    if (!not_primes[i]) {
      for (int j = i * i; j <= max_nr_divisors; j += i)
        not_primes[j] = true;
    }
}

int main()
{
  sieve_of_eratosthenes();
  for (int i = 1; i <= n_max; i++)
    for (int j = i; j <= n_max; j += i)
      nr_divisors[j]++;
  for (int i = 2; i <= n_max; i++)
    nr_divisors_primes[i] = !not_primes[nr_divisors[i]];
  int T;
  scanf("%d", &T);
  while (T--) {
    int L, H;
    scanf("%d %d", &L, &H);
    bool printed = false;
    for (int i = L; i <= H; i++)
      if (nr_divisors_primes[i]) {
        if (printed)
          putchar(' ');
        else
          printed = true;
        printf("%d", i);
      }
    if (printed)
      putchar('\n');
    else
      puts("-1");
  }
  return 0;
}

Friday, July 1, 2016

UVa 10874 - Segments

Accepted date: 2016-07-01
Run Time: 0.000
Ranking (as of 2016-07-01): 8 out of 442
Language: C++

/*
  UVa 10874 - Segments

  To build using Visual Studio 2012:
    cl -EHsc -O2 UVa_10874_Segments.cpp
*/

#include <algorithm>
#include <cstdio>
using namespace std;

const int n_max = 20000;

enum {left, right};
int segments[n_max][right - left + 1];
  // segments[i][left/right] is the left/right side of the i-th segments
int paths[n_max][right - left + 1];
  // paths[i][left/right] is the shortest path from (1, 1) 
  // to the left/right side of the i-th segments

int main()
{
  while (true) {
    int n;
    scanf("%d", &n);
    if (!n)
      break;
    for (int i = 0; i < n; i++)
      scanf("%d %d", &segments[i][left], &segments[i][right]);
    paths[0][left] = n + segments[0][right] - segments[0][left] - 1,
      paths[0][right] = segments[0][right] - 1;
#ifdef DEBUG
    printf("[0][%d]: %d\t[0][%d]: %d\n", left, paths[0][left], right, paths[0][right]);
#endif
    for (int i = 1; i < n; i++) {
      int sd = segments[i][right] - segments[i][left];
      int ld, rd;
      if (segments[i - 1][left] < segments[i][right])
        ld = segments[i][right] - segments[i - 1][left];
      else
        ld = segments[i - 1][left] - segments[i][right];
      if (segments[i - 1][right] < segments[i][right])
        rd = segments[i][right] - segments[i - 1][right];
      else
        rd = segments[i - 1][right] - segments[i][right];
      paths[i][left] = min(paths[i - 1][left] + ld + sd, paths[i - 1][right] + rd + sd) + 1;
      if (segments[i - 1][left] < segments[i][left])
        ld = segments[i][left] - segments[i - 1][left];
      else
        ld = segments[i - 1][left] - segments[i][left];
      if (segments[i - 1][right] < segments[i][left])
        rd = segments[i][left] - segments[i - 1][right];
      else
        rd = segments[i - 1][right] - segments[i][left];
      paths[i][right] = min(paths[i - 1][left] + ld + sd, paths[i - 1][right] + rd + sd) + 1;
#ifdef DEBUG
      printf("[%d][%d]: %d\t[%d][%d]: %d\n",
        i, left, paths[i][left], i, right, paths[i][right]);
#endif
    }
    printf("%d\n",
      min(paths[n - 1][left] + n - segments[n - 1][left],
      paths[n - 1][right] + n - segments[n - 1][right]));
  }
  return 0;
}