#include <bits/stdc++.h>   #pragma GCC optimize( Ofast )   const int nmax = 3e5 + 1;   using namespace std;   struct node {     int ind;     int cur;     node() {}     node(int cur, int ind) : cur(cur), ind(ind){};   };   node bolshe(node a, node b) {     return (a.cur == b.cur ? (a.ind > b.ind ? a : b) : (a.cur > b.cur ? a : b));   }   struct vertex {     vertex *l;     vertex *r;     int sum;     vertex(){};     vertex(int sum) : l(nullptr), r(nullptr), sum(sum){};     vertex(vertex *l, vertex *r) : l(l), r(r), sum(0) {       if (l != nullptr) sum += l->sum;       if (r != nullptr) sum += r->sum;     };   };   struct segment_tree {     node tr[nmax * 5];     int add[nmax * 5];     void build(vector<int> &a, int v, int cl, int cr) {       if (cl == cr) {         if (a[cl] > (cl + 1))           tr[v].cur = -1e9;         else           tr[v].cur = a[cl] - (cl + 1);         tr[v].ind = cl;         return;       }       int mid = (cl + cr) / 2;       build(a, v * 2, cl, mid);       build(a, v * 2 + 1, mid + 1, cr);       tr[v] = bolshe(tr[v * 2], tr[v * 2 + 1]);     }     void push(int v) {       add[v * 2] += add[v];       add[v * 2 + 1] += add[v];       tr[v].cur += add[v];       add[v] = 0;       return;     }     void increase(int v, int cl, int cr, int left, int right) {       if (left > right) return;       if (cl == left && cr == right) {         add[v] += 1;         return;       }       push(v);       int mid = (cl + cr) / 2;       increase(v * 2, cl, mid, left, min(right, mid));       increase(v * 2 + 1, mid + 1, cr, max(left, mid + 1), right);       tr[v] = bolshe(node(tr[v * 2].cur + add[v * 2], tr[v * 2].ind),                      node(tr[v * 2 + 1].cur + add[v * 2 + 1], tr[v * 2 + 1].ind));     }     void decrease(int v, int cl, int cr, int left, int right, int x) {       if (left > right) return;       if (cl == left && cr == right) {         add[v] -= x;         return;       }       push(v);       int mid = (cl + cr) / 2;       decrease(v * 2, cl, mid, left, min(right, mid), x);       decrease(v * 2 + 1, mid + 1, cr, max(left, mid + 1), right, x);       tr[v] = bolshe(node(tr[v * 2].cur + add[v * 2], tr[v * 2].ind),                      node(tr[v * 2 + 1].cur + add[v * 2 + 1], tr[v * 2 + 1].ind));     }     node find_max(int v, int cl, int cr, int left, int right) {       if (left > right) return node(-1e9, 1e9);       if (cl == left && cr == right) return node(tr[v].cur + add[v], tr[v].ind);       push(v);       int mid = (cl + cr) / 2;       return bolshe(find_max(v * 2, cl, mid, left, min(right, mid)),                     find_max(v * 2 + 1, mid + 1, cr, max(left, mid + 1), right));     }   };   segment_tree sg;   struct segment_tree_2 {     int tr[(int)(nmax * 5)];     void push(int v) {       if (tr[v] != -1) tr[v * 2] = tr[v * 2 + 1] = tr[v], tr[v] = -1;     }     void update(int v, int cl, int cr, int left, int right, int x) {       if (left > right) return;       if (cl == left && cr == right) {         tr[v] = x;         return;       }       push(v);       int mid = (cl + cr) / 2;       update(v * 2, cl, mid, left, min(right, mid), x);       update(v * 2 + 1, mid + 1, cr, max(left, mid + 1), right, x);     }     int get_number(int v, int cl, int cr, int pos) {       if (cl == cr) return tr[v];       push(v);       int mid = (cl + cr) / 2;       if (pos <= mid)         return get_number(v * 2, cl, mid, pos);       else         return get_number(v * 2 + 1, mid + 1, cr, pos);     }   };   segment_tree_2 sg2;   struct segment_tree_3 {     vector<int> tr[nmax * 5];     void build(vector<int> &a, int v, int cl, int cr) {       if (cl == cr) {         tr[v].push_back(a[cl]);         return;       }       int mid = (cl + cr) / 2;       build(a, v * 2, cl, mid);       build(a, v * 2 + 1, mid + 1, cr);       merge(tr[v * 2].begin(), tr[v * 2].end(), tr[v * 2 + 1].begin(),             tr[v * 2 + 1].end(), back_inserter(tr[v]));     }     int get(int v, int cl, int cr, int left, int right, int x) {       if (left > right) return 0;       if (cl == left && cr == right) {         int cur = lower_bound(tr[v].begin(), tr[v].end(), x) - tr[v].begin();         return tr[v].size() - cur;       }       int mid = (cl + cr) / 2;       return get(v * 2, cl, mid, left, min(right, mid), x) +              get(v * 2 + 1, mid + 1, cr, max(left, mid + 1), right, x);     }   };   segment_tree_3 sg3;   int32_t main() {     int n, m;     cin >> n >> m;     vector<int> a(n);     for (int i = 0; i < n; i += 1) cin >> a[i];     sg.build(a, 1, 0, n - 1);     sg2.update(1, 0, n - 1, 0, n - 1, 1e9);     vector<int> pr;     int lst = -1;     vector<int> need(n, -1e9);     while (1) {       node found = sg.find_max(1, 0, n - 1, 0, n - 1);       if (found.ind > n) break;       if (found.cur != 0) break;       int wow = sg2.get_number(1, 0, n - 1, found.ind);       if (wow == 1e9)         need[found.ind] = wow;       else if (need[wow] == 1e9)         need[found.ind] = wow;       else         need[found.ind] = need[wow];       pr.push_back(found.ind);       sg.increase(1, 0, n - 1, found.ind + 1, n - 1);       sg.decrease(1, 0, n - 1, found.ind, found.ind, 1e9);       sg2.update(1, 0, n - 1, found.ind + 1, n - 1, found.ind);     }     sg3.build(need, 1, 0, n - 1);     for (int i = 0; i < m; i += 1) {       int l, r;       cin >> l >> r;       r = n - 1 - r;       cout << sg3.get(1, 0, n - 1, l, r, l) <<   n ;     }   }