Problem p03790 (C++)

Buggy submission (status: Runtime Error):
#include <bits/stdc++.h>
using namespace std;
// Coded in Dongge Jifang 4

int n, k, N;
long long a[100005], b[100005];
long long qzh[100005];
long long liml[100005], limr[100005];
long long dp[100005], dp2[100005];
long long ans = 0x3f3f3f3f3f3f3f3fLL;

struct Node {
  long long num;
  Node *l, *r;
  Node() {
    num = n + 1;
    l = r = 0;
  }
} *root, *root2;

struct segtree {
  void init(Node *&now) {
    if (!now) {
      return;
    }
    init(now->l);
    init(now->r);
    delete now;
  }
  void update(int l, int r, long long x, Node *&now, int nl = 0,
              int nr = k - 1) {
    if (!now) {
      now = new Node();
    }
    if (nl >= l && nr <= r) {
      now->num = min(now->num, x);
      return;
    }
    if (nl > r || nr < l) {
      return;
    }
    int m = (nl + nr) >> 1;
    update(l, r, x, now->l, nl, m);
    update(l, r, x, now->r, m + 1, nr);
    // now->num=min(now->l->num,now->r->num);
  }
  void upd(int l, int r, long long x, Node *&now) {
    l = (l % k + k) % k;
    r = (r % k + k) % k;
    if (l <= r) {
      update(l, r, x, now);
    } else {
      update(l, k - 1, x, now);
      update(0, r, x, now);
    }
  }
  long long qmin(int whr, Node *&now, int nl = 0, int nr = k - 1) {
    if (!now) {
      now = new Node();
    }
    if (nl == whr && nr == whr) {
      return now->num;
    }
    int m = (nl + nr) >> 1;
    if (m >= whr) {
      return min(now->num, qmin(whr, now->l, nl, m));
    } else {
      return min(now->num, qmin(whr, now->r, m + 1, nr));
    }
  }
} seg1, seg2;

int main() {
  scanf("%d%d", &n, &k);
  for (int i = 1; i <= n; i++) {
    scanf("%lld%lld", a + i, b + i);
    if (b[i] == 1 && a[i] * 2 > k) {
      puts("-1");
      return 0;
    }
  }
  for (int i = 1; i <= n; i++) {
    qzh[i] = qzh[i - 1] + a[i];
  }
  for (int i = 1; i <= n; i++) {
    if (b[i] == 1) {
      liml[N] = 2 * (k - qzh[i] % k) % k;
      limr[N] = 2 * (k - qzh[i - 1] % k) % k;
      N++;
    }
  }
  seg1.init(root);
  seg2.init(root2);
  dp[N - 1] = dp2[N - 1] = 0;
  seg1.upd(liml[N - 1] + 1, limr[N - 1] - 1, N - 1, root);
  seg2.upd(liml[N - 1] + 1, limr[N - 1] - 1, N - 1, root2);
  // cerr<<liml[N-1]<<' '<<limr[N-1]<<endl;
  for (int i = N - 2; i >= 0; i--) {
    int x = seg1.qmin(liml[i], root);
    // cerr<<liml[i]<<' '<<' '<<x<<endl;
    if (x == n + 1) {
      dp[i] = 0;
    } else {
      dp[i] = min(dp[x] + ((liml[x] - liml[i]) % k + k) % k,
                  dp2[x] + ((limr[x] - liml[i]) % k + k) % k);
    }
    x = seg2.qmin(limr[i], root2);
    if (x == n + 1) {
      dp2[i] = 0;
    } else {
      dp2[i] = min(dp2[x] + ((limr[x] - limr[i]) % k + k) % k,
                   dp[x] + ((liml[x] - limr[i]) % k + k) % k);
    }
    seg1.upd(liml[i] + 1, limr[i] - 1, i, root);
    seg2.upd(liml[i] + 1, limr[i] - 1, i, root2);
  }
  seg1.init(root);
  seg2.init(root2);
  for (int i = 0; i < N; i++) {
    int x = seg1.qmin(liml[i], root);
    // cerr<<i<<' '<<x<<' '<<n<<' '<<dp[i]<<endl;
    if (x == n + 1) {
      ans = min(ans, dp[i]);
    }
    x = seg2.qmin(limr[i], root2);
    if (x == n + 1) {
      ans = min(ans, dp2[i]);
    }
    seg1.upd(liml[i] + 1, limr[i] - 1, i, root);
    seg2.upd(liml[i] + 1, limr[i] - 1, i, root2);
  }
  printf("%lld\n", ans + qzh[n] * 2);
  return 0;
}

Fixed submission:
#include <bits/stdc++.h>
using namespace std;
// Coded in Dongge Jifang 4

int n, k, N;
long long a[100005], b[100005];
long long qzh[100005];
long long liml[100005], limr[100005];
long long dp[100005], dp2[100005];
long long ans = 0x3f3f3f3f3f3f3f3fLL;

struct Node {
  long long num;
  Node *l, *r;
  Node() {
    num = n + 1;
    l = r = 0;
  }
} *root, *root2;

struct segtree {
  void init(Node *&now) {
    if (!now) {
      return;
    }
    init(now->l);
    init(now->r);
    delete now;
    now = 0;
  }
  void update(int l, int r, long long x, Node *&now, int nl = 0,
              int nr = k - 1) {
    if (!now) {
      now = new Node();
    }
    if (nl >= l && nr <= r) {
      now->num = min(now->num, x);
      return;
    }
    if (nl > r || nr < l) {
      return;
    }
    int m = (nl + nr) >> 1;
    update(l, r, x, now->l, nl, m);
    update(l, r, x, now->r, m + 1, nr);
    // now->num=min(now->l->num,now->r->num);
  }
  void upd(int l, int r, long long x, Node *&now) {
    l = (l % k + k) % k;
    r = (r % k + k) % k;
    if (l <= r) {
      update(l, r, x, now);
    } else {
      update(l, k - 1, x, now);
      update(0, r, x, now);
    }
  }
  long long qmin(int whr, Node *&now, int nl = 0, int nr = k - 1) {
    if (!now) {
      now = new Node();
    }
    if (nl == whr && nr == whr) {
      return now->num;
    }
    int m = (nl + nr) >> 1;
    if (m >= whr) {
      return min(now->num, qmin(whr, now->l, nl, m));
    } else {
      return min(now->num, qmin(whr, now->r, m + 1, nr));
    }
  }
} seg1, seg2;

int main() {
  scanf("%d%d", &n, &k);
  for (int i = 1; i <= n; i++) {
    scanf("%lld%lld", a + i, b + i);
    if (b[i] == 1 && a[i] * 2 > k) {
      puts("-1");
      return 0;
    }
  }
  for (int i = 1; i <= n; i++) {
    qzh[i] = qzh[i - 1] + a[i];
  }
  for (int i = 1; i <= n; i++) {
    if (b[i] == 1) {
      liml[N] = 2 * (k - qzh[i] % k) % k;
      limr[N] = 2 * (k - qzh[i - 1] % k) % k;
      N++;
    }
  }
  seg1.init(root);
  seg2.init(root2);
  dp[N - 1] = dp2[N - 1] = 0;
  seg1.upd(liml[N - 1] + 1, limr[N - 1] - 1, N - 1, root);
  seg2.upd(liml[N - 1] + 1, limr[N - 1] - 1, N - 1, root2);
  // cerr<<liml[N-1]<<' '<<limr[N-1]<<endl;
  for (int i = N - 2; i >= 0; i--) {
    int x = seg1.qmin(liml[i], root);
    // cerr<<liml[i]<<' '<<' '<<x<<endl;
    if (x == n + 1) {
      dp[i] = 0;
    } else {
      dp[i] = min(dp[x] + ((liml[x] - liml[i]) % k + k) % k,
                  dp2[x] + ((limr[x] - liml[i]) % k + k) % k);
    }
    x = seg2.qmin(limr[i], root2);
    if (x == n + 1) {
      dp2[i] = 0;
    } else {
      dp2[i] = min(dp2[x] + ((limr[x] - limr[i]) % k + k) % k,
                   dp[x] + ((liml[x] - limr[i]) % k + k) % k);
    }
    seg1.upd(liml[i] + 1, limr[i] - 1, i, root);
    seg2.upd(liml[i] + 1, limr[i] - 1, i, root2);
  }
  seg1.init(root);
  seg2.init(root2);
  for (int i = 0; i < N; i++) {
    int x = seg1.qmin(liml[i], root);
    // cerr<<i<<' '<<x<<' '<<n<<' '<<dp[i]<<endl;
    if (x == n + 1) {
      ans = min(ans, dp[i]);
    }
    x = seg2.qmin(limr[i], root2);
    if (x == n + 1) {
      ans = min(ans, dp2[i]);
    }
    seg1.upd(liml[i] + 1, limr[i] - 1, i, root);
    seg2.upd(liml[i] + 1, limr[i] - 1, i, root2);
  }
  printf("%lld\n", ans + qzh[n] * 2);
  return 0;
}