#include <bits/stdc++.h>
#define show(x) cerr << #x << " = " << x << endl
using namespace std;
using ll = long long;
template <typename T>
constexpr T INF = numeric_limits<T>::max() / 10;

template <typename Monoid>
class SegmentTree
{
public:
    using BaseMonoid = Monoid;
    using T = typename Monoid::T;

    SegmentTree(const int n) : data_num(n), size(1 << (1 + __lg(2 * data_num - 1))), half(size >> 1), value(size, Monoid::identity()) { assert(n > 0); }
    SegmentTree(const std::vector<T>& val) : data_num(val.size()), size(1 << (1 + __lg(2 * data_num - 1))), half(size >> 1), value(size)
    {
        for (int data = 0; data < half; data++) {
            if (data < data_num) {
                value[data + half] = val[data];
            } else {
                value[data + half] = Monoid::identity();
            }
        }
        for (int node = half - 1; node >= 1; node--) {
            value[node] = acc(value[2 * node], value[2 * node + 1]);
        }
    }
    T get(const int a) const
    {
        assert(0 <= a and a < data_num);
        return accumulate(a, a + 1);
    }
    void set(const int a, const T& val)
    {
        assert(0 <= a and a < data_num);
        const int node = a + half;
        value[node] = val;
        for (int i = node / 2; i > 0; i /= 2) {
            value[i] = acc(value[2 * i], value[2 * i + 1]);
        }
    }
    T accumulate(const int a, const int b) const  // Accumulate (a,b]
    {
        assert(0 <= a and a < b and b <= data_num);
        return accumulateRec(1, 0, half, a, b);
    }
    // F: queryの結果型
    // IntervalOperation: T -> F (区間に対するquery関数)
    // AccumulateOperation: F^2 -> F (異なる区間へのquery結果を統合する関数)
    template <typename F, typename IntervalOperation, typename AccumulateOperation>
    F query(const int a, const int b, const IntervalOperation& interval_op, const AccumulateOperation& accumulate_op) const
    {
        assert(0 <= a and a < b and b <= data_num);
        return queryRec<F>(1, 0, half, a, b, interval_op, accumulate_op);
    }
    // Predicate: T -> bool
    // pred: 単調性を満たす(つまり「 [a,x).accumulate.pred==true && [a,y).accumulate.pred==false <=> x < y 」を満たす)
    // [a,x).accumulate.pred == true となるxの上限を返す
    template <typename Predicate>
    int partitionPoint(const int a, const int b, const Predicate& pred) const
    {
        assert(0 <= a and a < b and b <= data_num);
        const int ans = partitionPointRec(1, 0, half, a, b, BaseMonoid::identity(), pred).second;
        if (ans == -1) {
            return b;
        } else {
            return ans;
        }
    }
    const int data_num;  // Num of valid data on leaves.
private:
    T accumulateRec(const int range_index, const int range_left, const int range_right, const int op_left, const int op_right) const
    {
        if (op_left <= range_left and range_right <= op_right) {
            return value[range_index];
        } else if (range_right <= op_left or op_right <= range_left) {
            return Monoid::identity();
        } else {
            return acc(accumulateRec(2 * range_index, range_left, (range_left + range_right) / 2, op_left, op_right),
                       accumulateRec(2 * range_index + 1, (range_left + range_right) / 2, range_right, op_left, op_right));
        }
    }
    template <typename F, typename IntervalOperation, typename AccumulateOperation>
    F queryRec(const int range_index, const int range_left, const int range_right, const int op_left, const int op_right, const IntervalOperation& interval_op, const AccumulateOperation& accumulate_op) const
    {
        if (op_left <= range_left and range_right <= op_right) {
            return interval_op(value[range_index]);
        } else if (range_right <= op_left or op_right <= range_left) {
            return 0;  // Identity of type F
        } else {
            const int L = queryRec<F>(2 * range_index, range_left, (range_left + range_right) / 2, op_left, op_right, interval_op, accumulate_op);
            const int R = queryRec<F>(2 * range_index + 1, (range_left + range_right) / 2, range_right, op_left, op_right, interval_op, accumulate_op);
            return accumulate_op(L, R);
        }
    }
    template <typename Predicate>
    pair<T, int> partitionPointRec(const int range_index, const int range_left, const int range_right, const int op_left, const int op_right, const T& offset, const Predicate& pred) const
    {
        if (range_right <= op_left or op_right <= range_left or pred(acc(offset, value[range_index]))) {
            return {Monoid::identity(), -1};
        }
        if (range_index >= half) {
            return {value[range_index], range_index - half};
        }
        const pair<T, int> L = partitionPointRec(2 * range_index, range_left, (range_left + range_right) / 2, op_left, op_right, offset, pred);
        if (L.second != -1) {
            return L;
        }
        return partitionPointRec(2 * range_index + 1, (range_left + range_right) / 2, range_right, op_left, op_right, acc(offset, L.first), pred);
    }
    const int size;
    const int half;
    vector<T> value;  // Tree for value(length: size)
    const Monoid acc{};
};
struct Min
{
    using T = ll;
    T operator()(const T& a, const T& b) const { return min(a, b); }
    static constexpr T identity() { return INF<T>; }
};
using Seg = SegmentTree<Min>;

int main()
{
    int N;
    cin >> N;
    vector<int> b(N);
    for (int i = 0; i < N; i++) {
        cin >> b[i];
    }

    using P = pair<int, int>;
    int Q;
    cin >> Q;
    vector<P> r(Q);
    for (int i = 0; i < Q; i++) {
        cin >> r[i].first >> r[i].second;
        r[i].first--;
    }
    sort(r.begin(), r.end());
    Seg dp(N + 1);
    int ind = 0;
    dp.set(0, 0);
    for (int l = 0; l < N; l++) {
        for (; ind < Q and r[ind].first == l; ind++) {
            dp.set(r[ind].second, dp.accumulate(r[ind].first, r[ind].second + 1));
        }
        dp.set(l + 1, min(dp.get(l) + (b[l] ? 1 : -1), dp.get(l + 1)));
    }
    cout << dp.get(N) + N - accumulate(b.begin(), b.end(), 0) << endl;
    return 0;
}


Measured memory_bytes: 6656