Problem p01471 (C++) — buggy submission, verdict: Runtime Error

#include <algorithm>
#include <cassert>
#include <cmath>
#include <cstdio>
#include <cstdlib>
#include <cstring>
#include <iostream>
#include <map>
#include <numeric>
#include <queue>
#include <set>
#include <sstream>
#include <stack>
#include <string>
#include <vector>

using namespace std;

#define FOR(i, k, n) for (int i = (k); i < (int)n; ++i)
#define REP(i, n) FOR(i, 0, n)
#define FORIT(i, c)                                                            \\
  for (__typeof((c).begin()) i = (c).begin(); i != (c).end(); ++i)

template <class T> void debug(T begin, T end) {
  for (T i = begin; i != end; ++i)
    cout << *i << " ";
  cout << endl;
}

typedef long long ll;
const int INF = 100000000;
const double EPS = 1e-8;
const int MOD = 1000000007;
typedef pair<double, double> P;
bool compare(P p, P q) {
  if ((double)p.second * q.first != (double)q.second * p.first)
    return (double)p.second * q.first > (double)q.second * p.first; // rev
  else
    return p.first < q.first;
}
bool compare2(P p, P q) {
  return !compare(p, q);
  if ((double)p.second / p.first != (double)q.second / q.first)
    return (double)p.second / p.first < (double)q.second / q.first; // rev
  else
    return p.first < q.first;
}

int main() {
  int N;
  ll W;
  while (cin >> N >> W && N) {
    vector<int> w(N), v(N);
    REP(i, N) cin >> w[i] >> v[i];
    vector<bool> used(N, 0);
    vector<P> get;
    vector<P> reduce;
    double ans = 0;
    REP(i, N) {
      if (w[i] == 0) {
        if (v[i] >= 0)
          ans += v[i];
        used[i] = true;
      } else if (w[i] < 0 && v[i] >= 0) {
        ans += v[i];
        W -= w[i];
        used[i] = true;
      } else if (w[i] > 0 && v[i] <= 0) {
        used[i] = true;
      }
    }
    REP(i, N) if (!used[i]) {
      if (w[i] > 0) {
        assert(v[i] > 0);
        get.push_back(P(w[i], v[i]));
      } else {
        assert(v[i] < 0);
        reduce.push_back(P(w[i], v[i]));
      }
    }
    sort(get.begin(), get.end(), compare);
    sort(reduce.begin(), reduce.end(), compare2);
    int r_idx = 0;
    REP(i, get.size()) {
      if (get[i].first <= W) {
        W -= get[i].first;
        ans += get[i].second;
      } else {
        while (r_idx < reduce.size() && get[i].first > W &&
               get[i].first / get[i].second <
                   reduce[r_idx].first / reduce[r_idx].second) {
          if (W - reduce[r_idx].first < get[i].first) {
            W -= reduce[r_idx].first;
            ans += reduce[r_idx].second;
            r_idx++;
          } else {
            double rest = get[i].first - W;
            assert(rest > 0);
            double use_p = rest / abs(reduce[r_idx].first);
            assert(abs(W - reduce[r_idx].first * use_p - get[i].first) < 0.001);
            W = get[i].first;
            ans += reduce[r_idx].second * use_p;
            reduce[r_idx].first += rest;
            reduce[r_idx].second =
                (reduce[r_idx].second - reduce[r_idx].second * use_p);
          }
        }
        if (get[i].first <= W) {
          W -= get[i].first;
          ans += get[i].second;
        } else if (W > 0) {
          double p = (double)W / get[i].first;
          assert(0 < p && p < 1);
          W = 0;
          ans += get[i].second * p;
        }
      }
    }
    printf("%.6lf\\n", ans);
  }
  return 0;
}

Error: 0

Fixed submission:

#include <algorithm>
#include <cassert>
#include <cmath>
#include <cstdio>
#include <cstdlib>
#include <cstring>
#include <iostream>
#include <map>
#include <queue>
#include <set>
#include <sstream>
#include <stack>
#include <string>
#include <vector>

using namespace std;

#define FOR(i, k, n) for (int i = (k); i < (int)n; ++i)
#define REP(i, n) FOR(i, 0, n)
#define FORIT(i, c)                                                            \\
  for (__typeof((c).begin()) i = (c).begin(); i != (c).end(); ++i)

template <class T> void debug(T begin, T end) {
  for (T i = begin; i != end; ++i)
    cout << *i << " ";
  cout << endl;
}

typedef long long ll;
const int INF = 100000000;
const double EPS = 1e-8;
const int MOD = 1000000007;
typedef pair<double, double> P;
bool compare(P p, P q) {
  if ((double)p.second / p.first != (double)q.second / q.first)
    return (double)p.second / p.first > (double)q.second / q.first; // rev
  else
    return p.first < q.first;
}
bool compare2(P p, P q) {
  if ((double)p.second / p.first != (double)q.second / q.first)
    return (double)p.second / p.first < (double)q.second / q.first; // rev
  else
    return p.first < q.first;
}

int main() {
  int N;
  ll W;
  while (cin >> N >> W && N) {
    vector<int> w(N), v(N);
    REP(i, N) cin >> w[i] >> v[i];
    vector<bool> used(N);
    vector<P> get;
    vector<P> reduce;
    double ans = 0;
    REP(i, N) {
      if (w[i] == 0) {
        if (v[i] >= 0)
          ans += v[i];
        used[i] = true;
      } else if (w[i] < 0 && v[i] >= 0) {
        ans += v[i];
        W -= w[i];
        used[i] = true;
      } else if (w[i] > 0 && v[i] <= 0) {
        used[i] = true;
      }
    }
    REP(i, N) if (!used[i]) {
      if (w[i] > 0) {
        assert(v[i] > 0);
        get.push_back(P(w[i], v[i]));
      } else {
        assert(v[i] < 0);
        reduce.push_back(P(w[i], v[i]));
      }
    }
    sort(get.begin(), get.end(), compare);
    sort(reduce.begin(), reduce.end(), compare2);
    int r_idx = 0;
    REP(i, get.size()) {
      if (get[i].first <= W) {
        W -= get[i].first;
        ans += get[i].second;
      } else {
        while (r_idx < reduce.size() && get[i].first > W &&
               get[i].first / get[i].second <
                   reduce[r_idx].first / reduce[r_idx].second) {
          if (W - reduce[r_idx].first < get[i].first) {
            W -= reduce[r_idx].first;
            ans += reduce[r_idx].second;
            r_idx++;
          } else {
            double rest = get[i].first - W;
            assert(rest > 0);
            double p =
                (abs(reduce[r_idx].first) - rest) / abs(reduce[r_idx].first);
            assert(0 < p && p < 1);
            W = get[i].first;
            ans += reduce[r_idx].second * (1 - p);
            reduce[r_idx].first *= p;
            reduce[r_idx].second *= p;
          }
        }
        if (get[i].first <= W) {
          W -= get[i].first;
          ans += get[i].second;
        } else {
          double p = (double)W / get[i].first;
          assert(0 < p && p < 1);
          W = 0;
          ans += get[i].second * p;
        }
      }
    }
    printf("%.6f\\n", ans);
  }
  return 0;
}