Problem p00523 (C++)

Buggy submission (status: Runtime Error):
#include <algorithm>
#include <cstdio>
#include <math.h>
#include <string.h>

const int INF = 1001001001;
#define rep(i, n) for (int i = 0; i < n; i++)
int N;
int A[200004];
long long int B[100002];

int main() {
  // FILE *fp;
  // fp=fopen("F:\\1JOI本選\\2014\\joi2014-ho-data\\joi2014-ho-data\\2014-ho-t3\\in\\03-06.txt","r");
  scanf("%d", &N);
  long long int MAX = 0;
  rep(i, N) {
    scanf("%d", &A[i]);
    MAX += A[i];
    B[i] = MAX;
  }
  memcpy(&A[N], A, sizeof(int) * N);

  long long int M = MAX / 3; // 全てのピースがM以上になる切り方は存在するか?
  long long int m = 0;
  do {
    bool cann = false; // 全てのピースがn以上になる切り方は存在するか?
    long long int n = (M + m) / 2;
    rep(i, N - 2) {  // どこで最初に切るか
      int a = i;     // よりあとで切る
      int b = N - 2; // 以前で切る
      do {           // 次に切る場所を探す
        int c = (a + b) / 2;
        long long int piece1 = B[c] - B[i];
        if (piece1 >= n) {
          b = c;
        } // c以前で切れる
        else
          a = c; // cよりあとで切るべき
      } while (b > a + 1);
      long long int p1 = B[b] - B[i];
      if (p1 < n)
        continue; // 1個目がもうだめ
      int x = b;
      int y = N - 1;
      do { // 最後に切る場所を探す
        int z = (x + y) / 2;
        long long int piece2 = B[z] - B[b];
        if (piece2 >= n) {
          y = z;
        } else
          x = z;
      } while (y > x + 1);
      long long int p2 = B[y] - B[b];
      if (p2 < n)
        continue; // 2個目がもうだめ
      if (MAX - p1 - p2 >= n) {
        cann = true;
      }
    }
    if (cann) {
      m = n;
    } // すべて(３つ)のピースがn以上になりえる
    else {
      M = n;
    }
  } while (M > m + 1);
  printf("%lld\n", m);
  return 1;
}

Fixed submission:
#include <algorithm>
#include <cstdio>
#include <math.h>
#include <string.h>

const int INF = 1001001001;
#define rep(i, n) for (int i = 0; i < n; i++)
int N;
int A[200004];
long long int B[100002];

int main() {
  // FILE *fp;
  // fp=fopen("F:\\1JOI本選\\2014\\joi2014-ho-data\\joi2014-ho-data\\2014-ho-t3\\in\\03-06.txt","r");
  scanf("%d", &N);
  long long int MAX = 0;
  rep(i, N) {
    scanf("%d", &A[i]);
    MAX += A[i];
    B[i] = MAX;
  }
  memcpy(&A[N], A, sizeof(int) * N);

  long long int M = MAX / 3; // 全てのピースがM以上になる切り方は存在するか?
  long long int m = 0;
  do {
    bool cann = false; // 全てのピースがn以上になる切り方は存在するか?
    long long int n = (M + m) / 2;
    rep(i, N - 2) {  // どこで最初に切るか
      int a = i;     // よりあとで切る
      int b = N - 2; // 以前で切る
      do {           // 次に切る場所を探す
        int c = (a + b) / 2;
        long long int piece1 = B[c] - B[i];
        if (piece1 >= n) {
          b = c;
        } // c以前で切れる
        else
          a = c; // cよりあとで切るべき
      } while (b > a + 1);
      long long int p1 = B[b] - B[i];
      if (p1 < n)
        continue; // 1個目がもうだめ
      int x = b;
      int y = N - 1;
      do { // 最後に切る場所を探す
        int z = (x + y) / 2;
        long long int piece2 = B[z] - B[b];
        if (piece2 >= n) {
          y = z;
        } else
          x = z;
      } while (y > x + 1);
      long long int p2 = B[y] - B[b];
      if (p2 < n)
        continue; // 2個目がもうだめ
      if (MAX - p1 - p2 >= n) {
        cann = true;
      }
    }
    if (cann) {
      m = n;
    } // すべて(３つ)のピースがn以上になりえる
    else {
      M = n;
    }
  } while (M > m + 1);
  printf("%lld\n", m);
  return 0;
}