Problem p03554 (C++)

Buggy submission (status: Runtime Error):
#include <algorithm>
#include <cmath>
#include <cstdio>
#include <cstdlib>
#include <cstring>
#include <iostream>
#include <string>
#define lson l, mid, rt << 1
#define rson mid + 1, r, rt << 1 | 1
#define ROOT 1, n, 1
#define deb cout << "----------------------------" << endl;
using namespace std;
const int maxn = 2e5 + 10;
const int INF = 0x3f3f3f3f;
inline void MIN(int &x, int y) {
  if (y < x)
    x = y;
}
struct adjs {
  int to, nx;
} edge[maxn];
int h[maxn], sz;
void init(int n) {
  for (int i = 0; i <= n; i++)
    h[i] = -1;
  sz = 0;
}
void addedge(int u, int v) {
  edge[sz].to = v;
  edge[sz].nx = h[u];
  h[u] = sz++;
}
int tree[maxn << 1];
void build(int l, int r, int rt) {
  tree[rt] = INF;
  if (l == r)
    return;
  int mid = (l + r) >> 1;
  build(lson);
  build(rson);
}
int query(int l, int r, int rt, int pos) {
  if (l == r)
    return tree[rt];
  int mid = (l + r) >> 1;
  if (pos <= mid)
    return min(query(lson, pos), tree[rt]);
  else
    return min(query(rson, pos), tree[rt]);
}
void update(int l, int r, int rt, int L, int R, int val) {
  if (L <= l && r <= R) {
    MIN(tree[rt], val);
    return;
  }
  int mid = (l + r) >> 1;
  if (L <= mid)
    update(lson, L, R, val);
  if (R > mid)
    update(rson, L, R, val);
}
void pt(int l, int r, int rt) {
  printf("[%d,%d]=%d\n", l, r, tree[rt]);
  if (l == r)
    return;
  int mid = (l + r) >> 1;
  pt(lson);
  pt(rson);
}
int n, a[maxn], sum[maxn], dp[maxn];
int m, u, v;
int main() {
#ifdef VGel
  freopen("F.in", "r", stdin);
  freopen("F.out", "w", stdout);
#endif // VGel
  while (~scanf("%d", &n)) {
    sum[0] = dp[0] = 0;
    for (int i = 1; i <= n; i++)
      scanf("%d", &a[i]), sum[i] = sum[i - 1] + !a[i];
    init(n);
    scanf("%d", &m);
    while (m--) {
      scanf("%d%d", &u, &v);
      addedge(v, u);
    }
    build(ROOT);
    //        pt(ROOT);deb;

    for (int r = 1; r <= n; r++) {
      dp[r] = dp[r - 1] + a[r];
      for (int i = h[r]; ~i; i = edge[i].nx) {
        int l = edge[i].to;
        int tmp = dp[l - 1] + sum[r] - sum[l - 1]; // xuan
        int tmp2 = query(ROOT, l) + sum[r];
        //                cout<<"l="<<l<<"  r="<<r<<"  tmp="<<tmp<<"
        //                tmp2="<<tmp2-sum[r]<<endl;
        MIN(tmp, tmp2);
        update(ROOT, l, r, tmp - sum[r]);
        MIN(dp[r], tmp);
        //                pt(ROOT);deb;
      }
    }
    printf("%d\n", dp[n]);
  }
  return 0;
}


Fixed submission:
#include <algorithm>
#include <cmath>
#include <cstdio>
#include <cstdlib>
#include <cstring>
#include <iostream>
#include <string>
#define lson l, mid, rt << 1
#define rson mid + 1, r, rt << 1 | 1
#define ROOT 1, n, 1
#define deb cout << "----------------------------" << endl;
using namespace std;
const int maxn = 2e5 + 10;
const int INF = 0x3f3f3f3f;
inline void MIN(int &x, int y) {
  if (y < x)
    x = y;
}
struct adjs {
  int to, nx;
} edge[maxn];
int h[maxn], sz;
void init(int n) {
  for (int i = 0; i <= n; i++)
    h[i] = -1;
  sz = 0;
}
void addedge(int u, int v) {
  edge[sz].to = v;
  edge[sz].nx = h[u];
  h[u] = sz++;
}
int tree[maxn << 2];
void build(int l, int r, int rt) {
  tree[rt] = INF;
  if (l == r)
    return;
  int mid = (l + r) >> 1;
  build(lson);
  build(rson);
}
int query(int l, int r, int rt, int pos) {
  if (l == r)
    return tree[rt];
  int mid = (l + r) >> 1;
  if (pos <= mid)
    return min(query(lson, pos), tree[rt]);
  else
    return min(query(rson, pos), tree[rt]);
}
void update(int l, int r, int rt, int L, int R, int val) {
  if (L <= l && r <= R) {
    MIN(tree[rt], val);
    return;
  }
  int mid = (l + r) >> 1;
  if (L <= mid)
    update(lson, L, R, val);
  if (R > mid)
    update(rson, L, R, val);
}
void pt(int l, int r, int rt) {
  printf("[%d,%d]=%d\n", l, r, tree[rt]);
  if (l == r)
    return;
  int mid = (l + r) >> 1;
  pt(lson);
  pt(rson);
}
int n, a[maxn], sum[maxn], dp[maxn];
int m, u, v;
int main() {
#ifdef VGel
  freopen("F.in", "r", stdin);
  freopen("F.out", "w", stdout);
#endif // VGel
  while (~scanf("%d", &n)) {
    sum[0] = dp[0] = 0;
    for (int i = 1; i <= n; i++)
      scanf("%d", &a[i]), sum[i] = sum[i - 1] + !a[i];
    init(n);
    scanf("%d", &m);
    while (m--) {
      scanf("%d%d", &u, &v);
      addedge(v, u);
    }
    build(ROOT);
    //        pt(ROOT);deb;

    for (int r = 1; r <= n; r++) {
      dp[r] = dp[r - 1] + a[r];
      for (int i = h[r]; ~i; i = edge[i].nx) {
        int l = edge[i].to;
        int tmp = dp[l - 1] + sum[r] - sum[l - 1]; // xuan
        int tmp2 = query(ROOT, l) + sum[r];
        //                cout<<"l="<<l<<"  r="<<r<<"  tmp="<<tmp<<"
        //                tmp2="<<tmp2-sum[r]<<endl;
        MIN(tmp, tmp2);
        update(ROOT, l, r, tmp - sum[r]);
        MIN(dp[r], tmp);
        //                pt(ROOT);deb;
      }
    }
    printf("%d\n", dp[n]);
  }
  return 0;
}