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

#include <algorithm>
#include <bitset>
#include <cassert>
#include <cmath>
#include <cstdio>
#include <cstdlib>
#include <ctime>
#include <deque>
#include <iostream>
#include <list>
#include <map>
#include <queue>
#include <set>
#include <stack>
#include <string>
#include <utility>
#include <vector>
#define llint long long
// #define double long double
#define inf 1e18
#define eps 1e-12
#define rep(x, s, t) for (llint(x) = (s); (x) < (t); (x)++)
#define Rep(x, s, t) for (llint(x) = (s); (x) <= (t); (x)++)
#define chmin(x, y) (x) = min((x), (y))
#define chmax(x, y) (x) = max((x), (y))

using namespace std;
typedef pair<double, llint> P;

struct Matrix {
  int h, w;
  vector<llint> mat;
  Matrix() { h = w = 0; }
  Matrix(int h, int w) {
    this->h = h, this->w = w;
    mat.resize(h * w);
  }
  llint &at(int i, int j) { return mat[w * (i - 1) + (j - 1)]; }
  static Matrix ident(int size) {
    Matrix ret(size, size);
    for (int i = 1; i <= size; i++)
      ret.at(i, i) = 1;
    return ret;
  }
  Matrix operator*(Matrix &ope) {
    Matrix ret(h, ope.w);
    for (int i = 1; i <= h; i++) {
      for (int j = 1; j <= ope.w; j++) {
        for (int k = 1; k <= w; k++) {
          ret.at(i, j) += at(i, k) * ope.at(k, j);
        }
      }
    }
    return ret;
  }
  void swaprows(Matrix &mat, llint i, llint j) {
    for (int k = 1; k <= mat.w; k++)
      swap(mat.at(i, k), mat.at(j, k));
  }
  Matrix inverse() {
    llint n = h;
    Matrix tmp(n, 2 * n);
    for (int i = 1; i <= n; i++) {
      for (int j = 1; j <= n; j++) {
        tmp.at(i, j) = at(i, j);
      }
    }
    for (int i = 1; i <= n; i++)
      tmp.at(i, n + i) = 1;

    for (int i = 1; i <= n; i++) {
      double max_val = 0;
      llint max_j = 0;
      for (int j = i; j <= n; j++) {
        if (max_val < fabs(tmp.at(j, i))) {
          max_val = fabs(tmp.at(j, i));
          max_j = j;
        }
      }
      swaprows(tmp, i, max_j);
      double x = tmp.at(i, i);
      for (int j = 1; j <= 2 * n; j++)
        tmp.at(i, j) /= x;
      for (int j = 1; j <= n; j++) {
        if (i == j)
          continue;
        double x = tmp.at(j, i);
        for (int k = 1; k <= 2 * n; k++) {
          tmp.at(j, k) -= x * tmp.at(i, k);
        }
      }
    }
    Matrix ret(n, n);
    for (int i = 1; i <= n; i++) {
      for (int j = 1; j <= n; j++) {
        ret.at(i, j) = tmp.at(i, n + j);
      }
    }
    return ret;
  }
  void print() {
    for (int i = 1; i <= h; i++) {
      for (int j = 1; j <= w; j++) {
        cout << at(i, j) << " ";
      }
      cout << endl;
    }
  }
};

llint n;
llint A[200005], B[200005];
double a[200005], b[200005];
double E[200005];

Matrix mat[200005], imat[200005];
Matrix mul[200005], imul[200005];
vector<P> vec;
double e[200005], d[200005];

bool flag;

double calc(llint p, double dec) {
  llint r = lower_bound(vec.begin(), vec.end(), P(dec, -inf)) - vec.begin() - 1;
  if (r < 0)
    r = 0;

  llint q = vec[r].second;
  // assert(q <= p);
  long double s = e[q], t = dec - d[q];
  double x = 2 * (s - t) + 2 * b[q] - e[q - 1];
  if (q == p)
    return max(a[q], (double)(s - t));

  Matrix res = mul[p - 1] * imul[q];

  /*if(p == 71249 && dec < 1e9){
          mul[p-1].print();
          imul[q].print();
          printf("%lld %.11f %.11f %.11f %.11f %.11f\\n", q, x, res.at(1, 1)*x,
  res.at(1, 2), e[q], res.at(1, 3)); res.print();
  }*/

  if (q == 1)
    return res.at(1, 1) * x + res.at(1, 2) * max(a[q], (double)(s - t)) +
           res.at(1, 3);
  else
    return res.at(1, 1) * x + res.at(1, 2) * e[q] + res.at(1, 3);
}

int main(void) {
  // ios::sync_with_stdio(0);
  // cin.tie(0);

  // cin >> n;
  scanf("%lld", &n);
  for (int i = 0; i < n; i++)
    scanf("%lld", &A[i]); // cin >> A[i];
  for (int i = 0; i < n; i++)
    scanf("%lld", &B[i]); // cin >> B[i];

  llint p = 0;
  for (int i = 0; i < n; i++) {
    if (A[p] < A[i])
      p = i;
  }
  for (int i = 0; i <= n; i++)
    a[i] = A[(i + p) % n], b[i] = B[(i + p) % n];
  E[0] = a[0];

  for (int i = 1; i < n; i++) {
    mat[i] = Matrix(3, 3);
    mat[i].at(1, 1) = 2, mat[i].at(1, 2) = -1;
    mat[i].at(2, 1) = 1, mat[i].at(3, 3) = 1;
    mat[i].at(1, 3) = 2 * b[i];
  }
  for (int i = 1; i < n; i++) {
    imat[i] = Matrix(3, 3);
    imat[i].at(1, 2) = 1, imat[i].at(2, 1) = -1;
    imat[i].at(2, 2) = 2, imat[i].at(2, 3) = 2 * b[i];
    imat[i].at(3, 3) = 1;
  }

  mul[0] = Matrix::ident(3);
  for (int i = 1; i < n; i++)
    mul[i] = mat[i] * mul[i - 1];

  imul[0] = Matrix::ident(3);
  for (int i = 1; i < n; i++)
    imul[i] = imul[i - 1] * imat[i];

  /*for(int i = 1; i < n; i++){
          Matrix x = mul[i] * imul[i];
          for(int j = 1; j <= 3; j++){
                  for(int k = 1; k <= 3; k++){
                          if(j != k && fabs(x.at(j, k)) > 1e-6){
                                  cout << i << endl;
                                  x.print();
                          }
                  }
          }
  }*/

  vec.push_back(P(0, 1));
  e[0] = e[1] = a[0], d[1] = 0;
  for (int i = 2; i <= n; i++) {
    double ub = 1e18, lb = 0, mid;
    for (int j = 0; j < 100; j++) {
      mid = (ub + lb) / 2;
      // if(i == 71249) printf("%.11f %.11f\\n", mid, calc(i, mid));
      if (calc(i, mid) <= a[i])
        ub = mid;
      else
        lb = mid;
    }
    d[i] = ub;
    while (vec.size() && vec.back().first > d[i])
      vec.pop_back();
    e[i] = calc(i, d[i]), e[i - 1] = max(e[i - 1], calc(i - 1, d[i]));
    vec.push_back(P(d[i], i));
  }

  // for(int i = 0; i <= n; i++) cout << d[i] << " "; cout << endl;

  flag = true;
  double dec = d[n], mn = inf;
  for (int i = n - 1; i >= 1; i--) {
    if (i > 1)
      mn = min(mn, d[i]);
    E[i] = max(a[i], calc(i, min(dec, mn)));
  }

  /*for(int i = 0; i < n; i++){
          double x = max(a[i], (E[(i+n-1)%n]+E[(i+1)%n])/2-b[i]);
          if(fabs(E[i] - x) > 1e-2) printf("%d %.15f %.15f\\n", i, E[i], x);
  }*/

  /*for(int i = 71240; i < 71300; i++){
          printf("%d %.11f %.11f\\n", i, e[i], d[i]);
  }*/

  double ans = 0;
  for (int i = 0; i < n; i++)
    ans += E[i];
  ans /= n;
  printf("%.30f\\n", ans);

  return 0;
}

Error: WA

Fixed submission:

#include <algorithm>
#include <bitset>
#include <cassert>
#include <cmath>
#include <cstdio>
#include <cstdlib>
#include <ctime>
#include <deque>
#include <iostream>
#include <list>
#include <map>
#include <queue>
#include <set>
#include <stack>
#include <string>
#include <utility>
#include <vector>
#define llint long long
#define inf 1e18
#define rep(x, s, t) for (llint(x) = (s); (x) < (t); (x)++)
#define Rep(x, s, t) for (llint(x) = (s); (x) <= (t); (x)++)
#define chmin(x, y) (x) = min((x), (y))
#define chmax(x, y) (x) = max((x), (y))

using namespace std;
typedef pair<double, llint> P;

struct Matrix {
  int h, w;
  vector<double> mat;
  Matrix() { h = w = 0; }
  Matrix(int h, int w) {
    this->h = h, this->w = w;
    mat.resize(h * w);
  }
  double &at(int i, int j) { return mat[w * (i - 1) + (j - 1)]; }
  static Matrix ident(int size) {
    Matrix ret(size, size);
    for (int i = 1; i <= size; i++)
      ret.at(i, i) = 1;
    return ret;
  }
  Matrix operator*(Matrix &ope) {
    Matrix ret(h, ope.w);
    for (int i = 1; i <= h; i++) {
      for (int j = 1; j <= ope.w; j++) {
        for (int k = 1; k <= w; k++) {
          ret.at(i, j) += at(i, k) * ope.at(k, j);
        }
      }
    }
    return ret;
  }
  void swaprows(Matrix &mat, llint i, llint j) {
    for (int k = 1; k <= mat.w; k++)
      swap(mat.at(i, k), mat.at(j, k));
  }
  Matrix inverse() {
    llint n = h;
    Matrix tmp(n, 2 * n);
    for (int i = 1; i <= n; i++) {
      for (int j = 1; j <= n; j++) {
        tmp.at(i, j) = at(i, j);
      }
    }
    for (int i = 1; i <= n; i++)
      tmp.at(i, n + i) = 1;

    for (int i = 1; i <= n; i++) {
      double max_val = 0;
      llint max_j = 0;
      for (int j = i; j <= n; j++) {
        if (max_val < fabs(tmp.at(j, i))) {
          max_val = fabs(tmp.at(j, i));
          max_j = j;
        }
      }
      swaprows(tmp, i, max_j);
      double x = tmp.at(i, i);
      for (int j = 1; j <= 2 * n; j++)
        tmp.at(i, j) /= x;
      for (int j = 1; j <= n; j++) {
        if (i == j)
          continue;
        double x = tmp.at(j, i);
        for (int k = 1; k <= 2 * n; k++) {
          tmp.at(j, k) -= x * tmp.at(i, k);
        }
      }
    }
    Matrix ret(n, n);
    for (int i = 1; i <= n; i++) {
      for (int j = 1; j <= n; j++) {
        ret.at(i, j) = tmp.at(i, n + j);
      }
    }
    return ret;
  }
  void print() {
    for (int i = 1; i <= h; i++) {
      for (int j = 1; j <= w; j++) {
        cout << at(i, j) << " ";
      }
      cout << endl;
    }
  }
};

llint n;
llint A[200005], B[200005];
double a[200005], b[200005];
double E[200005];

Matrix mat[200005], imat[200005];
Matrix mul[200005], imul[200005];
vector<P> vec;
double e[200005], d[200005];

bool flag;

double calc(llint p, double dec) {
  llint r = lower_bound(vec.begin(), vec.end(), P(dec, -inf)) - vec.begin() - 1;
  if (r < 0)
    r = 0;

  llint q = vec[r].second;
  assert(q <= p);
  double x = 2 * (e[q] - (dec - d[q])) + 2 * b[q] - e[q - 1];
  if (q == p)
    return max(a[q], e[q] - (dec - d[q]));

  Matrix res = mul[p - 1] * imul[q];
  if (q == 1) {
    double y = res.at(1, 1) * x +
               res.at(1, 2) * max(a[q], e[q] - (dec - d[q])) + res.at(1, 3);
    // if(flag && y <= a[p]-1e-10) cout << q << " " << p << " " << a[p] << " "
    // << y << endl;
    return y;
  } else {
    double y = res.at(1, 1) * x + res.at(1, 2) * e[q] + res.at(1, 3);
    // if(flag && y <= (1-1e-6)*a[p]) cout << q << " " << p << " " << y << " "
    // << a[p] << " " << dec << endl; assert(!flag || y > (1-1e-6)*a[p]);
    return y;
  }
}

int main(void) {
  ios::sync_with_stdio(0);
  cin.tie(0);

  cin >> n;
  for (int i = 0; i < n; i++)
    cin >> A[i];
  for (int i = 0; i < n; i++)
    cin >> B[i];

  llint p = 0;
  for (int i = 0; i < n; i++) {
    if (A[p] < A[i])
      p = i;
  }
  for (int i = 0; i <= n; i++)
    a[i] = A[(i + p) % n], b[i] = B[(i + p) % n];
  E[0] = a[0];

  for (int i = 1; i < n; i++) {
    mat[i] = Matrix(3, 3);
    mat[i].at(1, 1) = 2, mat[i].at(1, 2) = -1;
    mat[i].at(2, 1) = 1, mat[i].at(3, 3) = 1;
    mat[i].at(1, 3) = 2 * b[i];
    imat[i] = mat[i].inverse();
  }

  mul[0] = Matrix::ident(3);
  for (int i = 1; i < n; i++)
    mul[i] = mat[i] * mul[i - 1];

  imul[0] = Matrix::ident(3);
  for (int i = 1; i < n; i++)
    imul[i] = imul[i - 1] * imat[i];

  vec.push_back(P(0, 1));
  e[0] = e[1] = a[0], d[1] = 0;
  for (int i = 2; i <= n; i++) {
    double ub = 1e18, lb = 0, mid;
    for (int j = 0; j < 100; j++) {
      mid = (ub + lb) / 2;
      if (calc(i, mid) <= a[i])
        ub = mid;
      else
        lb = mid;
    }
    d[i] = ub;
    while (vec.size() && vec.back().first >= d[i] - 1e-12)
      vec.pop_back();
    e[i] = calc(i, d[i]), e[i - 1] = max(e[i - 1], calc(i - 1, d[i]));
    vec.push_back(P(d[i], i));
  }

  // for(int i = 0; i <= n; i++) cout << d[i] << " "; cout << endl;

  flag = true;
  double dec = d[n], mn = inf;
  for (int i = n - 1; i >= 1; i--) {
    if (i > 1)
      mn = min(mn, d[i]);
    E[i] = max(a[i], calc(i, min(dec, mn)));
  }

  // for(int i = 0; i < n; i++) cout << i << " " << E[i] << " " << max(a[i],
  // (E[(i+n-1)%n]+E[(i+1)%n])/2-b[i]) << endl;

  double ans = 0;
  for (int i = 0; i < n; i++)
    ans += E[i];
  ans /= n;
  printf("%.30f\\n", ans);

  return 0;
}