/**
 * code generated by JHelper
 * More info: https://github.com/AlexeyDmitriev/JHelper
 * @author majk
 */

#ifndef MAJK_LIB
#define MAJK_LIB

#include <vector>
#include <stack>
#include <iostream>
#include <unordered_map>
#include <unordered_set>
#include <map>
#include <iomanip>
#include <set>
#include <functional>
#include <algorithm>
#include <numeric>
#include <cassert>
#include <cmath>
#include <string>
#include <queue>
#include <array>
#include <bitset>
using namespace std;

#define x first
#define y second
typedef std::pair<int,int> pii; typedef long long ll; typedef unsigned long long ull; typedef unsigned int ui; typedef pair<ui,ui> puu;

template <typename T, typename U> std::istream&operator>>(std::istream&i, pair<T,U>&p) {i >> p.x >> p.y; return i;}
template<typename T>std::istream&operator>>(std::istream&i,vector<T>&t) {for(auto&v:t){i>>v;}return i;}
template <typename T, typename U> std::ostream&operator<<(std::ostream&o, const pair<T,U>&p) {o << p.x << ' ' << p.y; return o;}
template<typename T>std::ostream&operator<<(std::ostream&o,const vector<T>&t) {if(t.empty())o<<'\n';for(size_t i=0;i<t.size();++i){o<<t[i]<<" \n"[i == t.size()-1];}return o;}
template<typename T> using minheap = priority_queue<T, vector<T>, greater<T>>;
template<typename T> using maxheap = priority_queue<T, vector<T>, less<T>>;
ui logceil(ll x) { return x?8*sizeof(ll)-__builtin_clzll(x):0; }

namespace std { template<typename T,typename U>struct hash<pair<T,U>>{hash<T>t;hash<U>u;size_t operator()(const pair<T,U>&p)const{return t(p.x)^(u(p.y)<<7);}}; }
template<typename T,typename F>T bsh(T l,T h,const F&f){T r=-1,m;while(l<=h){m=(l+h)/2;if(f(m)){l=m+1;r=m;}else{h=m-1;}}return r;}
template<typename F> double bshd(double l,double h,const F&f,double p=1e-9){ui r=3+(ui)log2((h-l)/p);while(r--){double m=(l+h)/2;if(f(m)){l=m;}else{h=m;}}return (l+h)/2;}
template<typename T,typename F>T bsl(T l,T h,const F&f){T r=-1,m;while(l<=h){m=(l+h)/2;if(f(m)){h=m-1;r=m;}else{l=m+1;}}return r;}
template<typename F> double bsld(double l,double h,const F&f,double p=1e-9){ui r=3+(ui)log2((h-l)/p);while(r--){double m=(l+h)/2;if(f(m)){h=m;}else{l=m;}}return (l+h)/2;}
template<typename T> T gcd(T a,T b) { if (a<b) swap(a,b); return b?gcd(b,a%b):a; }

template<typename T>class vector2:public vector<vector<T>>{public:vector2(){} vector2(size_t a,size_t b,T t=T()):vector<vector<T>>(a,vector<T>(b,t)){}};
template<typename T>class vector3:public vector<vector2<T>>{public:vector3(){} vector3(size_t a,size_t b,size_t c,T t=T()):vector<vector2<T>>(a,vector2<T>(b,c,t)){}};
template<typename T>class vector4:public vector<vector3<T>>{public:vector4(){} vector4(size_t a,size_t b,size_t c,size_t d,T t=T()):vector<vector3<T>>(a,vector3<T>(b,c,d,t)){}};
template<typename T>class vector5:public vector<vector4<T>>{public:vector5(){} vector5(size_t a,size_t b,size_t c,size_t d,size_t e,T t=T()):vector<vector4<T>>(a,vector4<T>(b,c,d,e,t)){}};

#endif

class HNumberOfComponents {
public:
    int N, Q;
    vector<int> A;

    struct Comp {
        int i, j;
        int lo, hi;
    };

    struct Block {
        vector<Comp> C;
    };

    void build(Block&block, int from, int to) {
        block.C.clear();
        for (int i = from; i < to; ++i) {
            Comp c = {i,i,A[i],A[i]};
            while (!block.C.empty() && block.C.back().lo < c.hi) {
                c = {block.C.back().i, c.j, min(block.C.back().lo, c.lo), max(block.C.back().hi, c.hi)};
                block.C.pop_back();
            }
            block.C.push_back(c);
        }
    }

    vector<Block> Blocks;

    struct BlockGroup {
        int blockId;
        int from, to;
        int lo, hi;
    };

    void solve(istream& cin, ostream& cout) {
        cin >> N >> Q;
        A.resize(N);
        cin >> A;

        int S = 500;
        int B = (N+S-1)/S;
        Blocks.resize(B);
        for (int i = 0; i < B; ++i) {
            build(Blocks[i], i*S, min(i*S+S, N));
        }
        for (int q = 0; q < Q; ++q) {
            int p, x; cin >> p >> x;
            --p;
            int b = p/S;
            A[p] = x;
            build(Blocks[b], b*S, min(N, b*S+S));

            vector<BlockGroup> Groups;
            for (int i = 0; i < B; ++i) {
                auto &block = Blocks[i].C;
                int j = bsh(0, (int)block.size()-1, [&](int x) { return !Groups.empty() && Groups.back().lo < block[x].hi; });
                if (j == -1) {
                    Groups.push_back(BlockGroup{i, 0, (int)block.size(), block.back().lo, block[0].hi});
                } else {
                    BlockGroup BG{-1, 0, 1, block.back().lo, block[0].hi};
                    while (!Groups.empty() && Groups.back().lo < BG.hi) {
                        auto &last = Groups.back();
                        if (last.blockId == -1) {
                            BG.lo = min(BG.lo, last.lo);
                            BG.hi = max(BG.hi, last.hi);
                            Groups.pop_back();
                        } else {
                            auto &lastB = Blocks[last.blockId].C;
                            if (lastB[last.from].lo < BG.hi) {
                                BG.lo = min(BG.lo, last.lo);
                                BG.hi = max(BG.hi, last.hi);
                                Groups.pop_back();
                            } else {
                                int s = bsl(last.from, last.to - 1, [&](int x) { return lastB[x].lo < BG.hi; });
                                last.lo = 1000000000;
                                last.hi = 0;
                                last.to = s;
                                for (int k = 0; k < s; ++k) {
                                    last.lo = min(last.lo, lastB[k].lo);
                                    last.hi = max(last.hi, lastB[k].hi);
                                }

                                for (int k = s; k < last.to; ++k) {
                                    BG.lo = min(BG.lo, lastB[k].lo);
                                    BG.hi = max(BG.hi, lastB[k].hi);
                                }
                            }
                        }
                    }
                    Groups.push_back(BG);
                    if (j+1 != (int)block.size()) {
                        Groups.push_back(BlockGroup{i, j+1, (int)block.size(), block.back().lo, block[j+1].hi});
                    }
                }
            }

            int ans = 0;
            for (BlockGroup&bg: Groups) ans += bg.to - bg.from;
            cout << ans << '\n';
        }
    }
};

int main() {
	ios_base::sync_with_stdio(false); cin.tie(nullptr); cout.tie(nullptr);
	HNumberOfComponents solver;
	std::istream& in(std::cin);
	std::ostream& out(std::cout);
	solver.solve(in, out);
    return 0;
}


/**
 * code generated by JHelper
 * More info: https://github.com/AlexeyDmitriev/JHelper
 * @author majk
 */

#ifndef MAJK_LIB
#define MAJK_LIB

#include <vector>
#include <stack>
#include <iostream>
#include <unordered_map>
#include <unordered_set>
#include <map>
#include <iomanip>
#include <set>
#include <functional>
#include <algorithm>
#include <numeric>
#include <cassert>
#include <cmath>
#include <string>
#include <queue>
#include <array>
#include <bitset>
using namespace std;

#define x first
#define y second
typedef std::pair<int,int> pii; typedef long long ll; typedef unsigned long long ull; typedef unsigned int ui; typedef pair<ui,ui> puu;

template <typename T, typename U> std::istream&operator>>(std::istream&i, pair<T,U>&p) {i >> p.x >> p.y; return i;}
template<typename T>std::istream&operator>>(std::istream&i,vector<T>&t) {for(auto&v:t){i>>v;}return i;}
template <typename T, typename U> std::ostream&operator<<(std::ostream&o, const pair<T,U>&p) {o << p.x << ' ' << p.y; return o;}
template<typename T>std::ostream&operator<<(std::ostream&o,const vector<T>&t) {if(t.empty())o<<'\n';for(size_t i=0;i<t.size();++i){o<<t[i]<<" \n"[i == t.size()-1];}return o;}
template<typename T> using minheap = priority_queue<T, vector<T>, greater<T>>;
template<typename T> using maxheap = priority_queue<T, vector<T>, less<T>>;
ui logceil(ll x) { return x?8*sizeof(ll)-__builtin_clzll(x):0; }

namespace std { template<typename T,typename U>struct hash<pair<T,U>>{hash<T>t;hash<U>u;size_t operator()(const pair<T,U>&p)const{return t(p.x)^(u(p.y)<<7);}}; }
template<typename T,typename F>T bsh(T l,T h,const F&f){T r=-1,m;while(l<=h){m=(l+h)/2;if(f(m)){l=m+1;r=m;}else{h=m-1;}}return r;}
template<typename F> double bshd(double l,double h,const F&f,double p=1e-9){ui r=3+(ui)log2((h-l)/p);while(r--){double m=(l+h)/2;if(f(m)){l=m;}else{h=m;}}return (l+h)/2;}
template<typename T,typename F>T bsl(T l,T h,const F&f){T r=-1,m;while(l<=h){m=(l+h)/2;if(f(m)){h=m-1;r=m;}else{l=m+1;}}return r;}
template<typename F> double bsld(double l,double h,const F&f,double p=1e-9){ui r=3+(ui)log2((h-l)/p);while(r--){double m=(l+h)/2;if(f(m)){h=m;}else{l=m;}}return (l+h)/2;}
template<typename T> T gcd(T a,T b) { if (a<b) swap(a,b); return b?gcd(b,a%b):a; }

template<typename T>class vector2:public vector<vector<T>>{public:vector2(){} vector2(size_t a,size_t b,T t=T()):vector<vector<T>>(a,vector<T>(b,t)){}};
template<typename T>class vector3:public vector<vector2<T>>{public:vector3(){} vector3(size_t a,size_t b,size_t c,T t=T()):vector<vector2<T>>(a,vector2<T>(b,c,t)){}};
template<typename T>class vector4:public vector<vector3<T>>{public:vector4(){} vector4(size_t a,size_t b,size_t c,size_t d,T t=T()):vector<vector3<T>>(a,vector3<T>(b,c,d,t)){}};
template<typename T>class vector5:public vector<vector4<T>>{public:vector5(){} vector5(size_t a,size_t b,size_t c,size_t d,size_t e,T t=T()):vector<vector4<T>>(a,vector4<T>(b,c,d,e,t)){}};

#endif

class HNumberOfComponents {
public:
    int N, Q;
    vector<int> A;

    struct Comp {
        int i, j;
        int lo, hi;
    };

    struct Block {
        vector<Comp> C;
    };

    void build(Block&block, int from, int to) {
        block.C.clear();
        for (int i = from; i < to; ++i) {
            Comp c = {i,i,A[i],A[i]};
            while (!block.C.empty() && block.C.back().lo < c.hi) {
                c = {block.C.back().i, c.j, min(block.C.back().lo, c.lo), max(block.C.back().hi, c.hi)};
                block.C.pop_back();
            }
            block.C.push_back(c);
        }
    }

    vector<Block> Blocks;

    struct BlockGroup {
        int blockId;
        int from, to;
        int lo, hi;
    };

    void solve(istream& cin, ostream& cout) {
        cin >> N >> Q;
        A.resize(N);
        cin >> A;

        int S = 500;
        int B = (N+S-1)/S;
        Blocks.resize(B);
        for (int i = 0; i < B; ++i) {
            build(Blocks[i], i*S, min(i*S+S, N));
        }
        for (int q = 0; q < Q; ++q) {
            int p, x; cin >> p >> x;
            --p;
            int b = p/S;
            A[p] = x;
            build(Blocks[b], b*S, min(N, b*S+S));

            vector<BlockGroup> Groups;
            for (int i = 0; i < B; ++i) {
                int j = bsh(0, (int)Blocks[i].C.size()-1, [&](int x) {
                    return !Groups.empty() && Groups.back().lo < Blocks[i].C[x].hi;
                });
                if (j == -1) {
                    Groups.push_back(BlockGroup{i, 0, (int)Blocks[i].C.size(), Blocks[i].C.back().lo, Blocks[i].C[0].hi});
                } else {
                    BlockGroup BG{-1, -1, -1, Blocks[i].C.back().lo, Blocks[i].C[0].hi};
                    while (!Groups.empty() && Groups.back().lo < BG.hi) {
                        if (Blocks[Groups.back().blockId].C[Groups.back().from].lo < BG.hi) {
                            BG.lo = min(BG.lo, Groups.back().lo);
                            BG.hi = min(BG.hi, Groups.back().hi);
                            Groups.pop_back();
                        } else {
                            int s = bsl(Groups.back().from, Groups.back().to-1, [&](int x) {
                                return Blocks[Groups.back().blockId].C[x].lo < BG.hi;
                            });
                            Groups.back().lo = 100000000;
                            Groups.back().hi = 0;
                            Groups.back().to = s;
                            for (int k = s; k < Groups.back().to; ++k) {
                                BG.lo = min(BG.lo, Blocks[Groups.back().blockId].C[k].lo);
                                BG.hi = min(BG.hi, Blocks[Groups.back().blockId].C[k].hi);
                            }
                            for (int k = 0; k < s; ++k) {
                                Groups.back().lo = max(Groups.back().lo,  Blocks[Groups.back().blockId].C[k].lo);
                                Groups.back().hi = max(Groups.back().hi,  Blocks[Groups.back().blockId].C[k].hi);
                            }
                        }
                    }
                    Groups.push_back(BG);
                    if (j != (int)Blocks[i].C.size()-1) {
                        Groups.push_back(BlockGroup{i, j+1, (int)Blocks[i].C.size(), Blocks[i].C.back().lo, Blocks[i].C[j+1].hi});
                    }
                }
            }

            int ans = 0;
            for (BlockGroup&bg: Groups) {
//                cout << bg.blockId << ' ' << bg.from << ' ' << bg.to << ' ' << bg.lo << ' ' << bg.hi << endl;
                if (bg.blockId == -1) ans++;
                else ans += bg.to - bg.from;
            }
            cout << ans << '\n';
        }
    }
};

int main() {
	ios_base::sync_with_stdio(false); cin.tie(nullptr); cout.tie(nullptr);
	HNumberOfComponents solver;
	std::istream& in(std::cin);
	std::ostream& out(std::cout);
	solver.solve(in, out);
    return 0;
}


/**
 * code generated by JHelper
 * More info: https://github.com/AlexeyDmitriev/JHelper
 * @author majk
 */

#ifndef MAJK_LIB
#define MAJK_LIB

#include <vector>
#include <stack>
#include <iostream>
#include <unordered_map>
#include <unordered_set>
#include <map>
#include <iomanip>
#include <set>
#include <functional>
#include <algorithm>
#include <numeric>
#include <cassert>
#include <cmath>
#include <string>
#include <queue>
#include <array>
#include <bitset>
using namespace std;

#define x first
#define y second
typedef std::pair<int,int> pii; typedef long long ll; typedef unsigned long long ull; typedef unsigned int ui; typedef pair<ui,ui> puu;

template <typename T, typename U> std::istream&operator>>(std::istream&i, pair<T,U>&p) {i >> p.x >> p.y; return i;}
template<typename T>std::istream&operator>>(std::istream&i,vector<T>&t) {for(auto&v:t){i>>v;}return i;}
template <typename T, typename U> std::ostream&operator<<(std::ostream&o, const pair<T,U>&p) {o << p.x << ' ' << p.y; return o;}
template<typename T>std::ostream&operator<<(std::ostream&o,const vector<T>&t) {if(t.empty())o<<'\n';for(size_t i=0;i<t.size();++i){o<<t[i]<<" \n"[i == t.size()-1];}return o;}
template<typename T> using minheap = priority_queue<T, vector<T>, greater<T>>;
template<typename T> using maxheap = priority_queue<T, vector<T>, less<T>>;
ui logceil(ll x) { return x?8*sizeof(ll)-__builtin_clzll(x):0; }

namespace std { template<typename T,typename U>struct hash<pair<T,U>>{hash<T>t;hash<U>u;size_t operator()(const pair<T,U>&p)const{return t(p.x)^(u(p.y)<<7);}}; }
template<typename T,typename F>T bsh(T l,T h,const F&f){T r=-1,m;while(l<=h){m=(l+h)/2;if(f(m)){l=m+1;r=m;}else{h=m-1;}}return r;}
template<typename F> double bshd(double l,double h,const F&f,double p=1e-9){ui r=3+(ui)log2((h-l)/p);while(r--){double m=(l+h)/2;if(f(m)){l=m;}else{h=m;}}return (l+h)/2;}
template<typename T,typename F>T bsl(T l,T h,const F&f){T r=-1,m;while(l<=h){m=(l+h)/2;if(f(m)){h=m-1;r=m;}else{l=m+1;}}return r;}
template<typename F> double bsld(double l,double h,const F&f,double p=1e-9){ui r=3+(ui)log2((h-l)/p);while(r--){double m=(l+h)/2;if(f(m)){h=m;}else{l=m;}}return (l+h)/2;}
template<typename T> T gcd(T a,T b) { if (a<b) swap(a,b); return b?gcd(b,a%b):a; }

template<typename T>class vector2:public vector<vector<T>>{public:vector2(){} vector2(size_t a,size_t b,T t=T()):vector<vector<T>>(a,vector<T>(b,t)){}};
template<typename T>class vector3:public vector<vector2<T>>{public:vector3(){} vector3(size_t a,size_t b,size_t c,T t=T()):vector<vector2<T>>(a,vector2<T>(b,c,t)){}};
template<typename T>class vector4:public vector<vector3<T>>{public:vector4(){} vector4(size_t a,size_t b,size_t c,size_t d,T t=T()):vector<vector3<T>>(a,vector3<T>(b,c,d,t)){}};
template<typename T>class vector5:public vector<vector4<T>>{public:vector5(){} vector5(size_t a,size_t b,size_t c,size_t d,size_t e,T t=T()):vector<vector4<T>>(a,vector4<T>(b,c,d,e,t)){}};

#endif

class HNumberOfComponents {
public:
    int N, Q;
    vector<int> A;

    void build(vector<pii>&block, int from, int to) {
        block.clear();
        for (int i = from; i < to; ++i) {
            pii c = {A[i],A[i]};
            while (!block.empty() && block.back().x < c.y) {
                c = {min(block.back().x, c.x), max(block.back().y, c.y)};
                block.pop_back();
            }
            block.push_back(c);
        }
    }

    vector<vector<pii>> Blocks;

    struct BlockGroup {
        int blockId;
        int from, to;
        int lo, hi;
    };

    void solve(istream& cin, ostream& cout) {
        cin >> N >> Q;
        A.resize(N);
        cin >> A;

        int S = 2048;
        int B = (N+S-1)/S;
        Blocks.resize(B);
        for (int i = 0; i < B; ++i) {
            build(Blocks[i], i*S, min(i*S+S, N));
        }
        vector<unordered_map<int, int>> CacheL(B);
        vector<unordered_map<int, int>> CacheR(B);
        for (int q = 0; q < Q; ++q) {
            int p, x; cin >> p >> x;
            --p;
            int b = p/S;
            A[p] = x;
            build(Blocks[b], b*S, min(N, b*S+S));
            CacheL[b].clear();
            CacheR[b].clear();

            vector<BlockGroup> Groups;
            for (int i = 0; i < B; ++i) {
                auto &block = Blocks[i];
                if (Groups.empty() || Groups.back().lo >= block[0].y) {
                    Groups.push_back(BlockGroup{i, 0, (int)block.size(), block.back().x, block[0].y});
                } else {
                    int j;
                    if (Groups.back().lo < block[(int)block.size()-1].y) {
                        j = (int)block.size()-1;
                    } else {
                        auto it = CacheR[i].find(Groups.back().lo);
                        if (it != CacheR[i].end()) j = it->y;
                        else j = CacheR[i][Groups.back().lo] = bsh(0, (int)block.size()-1, [&](int x) { return Groups.back().lo < block[x].y; });
                    }
                    BlockGroup BG{-1, 0, 1, block.back().x, block[0].y};
                    while (!Groups.empty() && Groups.back().lo < BG.hi) {
                        auto &last = Groups.back();
                        if (last.blockId == -1) {
                            BG.lo = min(BG.lo, last.lo);
                            BG.hi = max(BG.hi, last.hi);
                            Groups.pop_back();
                        } else {
                            auto &lastB = Blocks[last.blockId];
                            if (lastB[last.from].x < BG.hi) {
                                BG.lo = min(BG.lo, last.lo);
                                BG.hi = max(BG.hi, last.hi);
                                Groups.pop_back();
                            } else {
                                auto it = CacheL[last.blockId].find(BG.hi);
                                int s = (it != CacheL[last.blockId].find(BG.hi)) ? it->y : CacheL[last.blockId][BG.hi] = bsl(last.from, last.to - 1, [&](int x) { return lastB[x].x < BG.hi; });
                                BG.lo = min(BG.lo, lastB[last.to-1].x);
                                BG.hi = max(BG.hi, lastB[s].y);
                                last.lo = lastB[s-1].x;
                                last.hi = lastB[last.from].y;
                                last.to = s;
                            }
                        }
                    }
                    Groups.push_back(BG);
                    if (j+1 != (int)block.size()) {
                        Groups.push_back(BlockGroup{i, j+1, (int)block.size(), block.back().x, block[j+1].y});
                    }
                }
            }

            int ans = 0;
            for (BlockGroup&bg: Groups) ans += bg.to - bg.from;
            cout << ans << '\n';
        }
    }
};

int main() {
	ios_base::sync_with_stdio(false); cin.tie(nullptr); cout.tie(nullptr);
	HNumberOfComponents solver;
	std::istream& in(std::cin);
	std::ostream& out(std::cout);
	solver.solve(in, out);
    return 0;
}


/**
 * code generated by JHelper
 * More info: https://github.com/AlexeyDmitriev/JHelper
 * @author majk
 */

#ifndef MAJK_LIB
#define MAJK_LIB

#include <vector>
#include <stack>
#include <iostream>
#include <unordered_map>
#include <unordered_set>
#include <map>
#include <iomanip>
#include <set>
#include <functional>
#include <algorithm>
#include <numeric>
#include <cassert>
#include <cmath>
#include <string>
#include <queue>
#include <array>
#include <bitset>
using namespace std;

#define x first
#define y second
typedef std::pair<int,int> pii; typedef long long ll; typedef unsigned long long ull; typedef unsigned int ui; typedef pair<ui,ui> puu;

template <typename T, typename U> std::istream&operator>>(std::istream&i, pair<T,U>&p) {i >> p.x >> p.y; return i;}
template<typename T>std::istream&operator>>(std::istream&i,vector<T>&t) {for(auto&v:t){i>>v;}return i;}
template <typename T, typename U> std::ostream&operator<<(std::ostream&o, const pair<T,U>&p) {o << p.x << ' ' << p.y; return o;}
template<typename T>std::ostream&operator<<(std::ostream&o,const vector<T>&t) {if(t.empty())o<<'\n';for(size_t i=0;i<t.size();++i){o<<t[i]<<" \n"[i == t.size()-1];}return o;}
template<typename T> using minheap = priority_queue<T, vector<T>, greater<T>>;
template<typename T> using maxheap = priority_queue<T, vector<T>, less<T>>;
ui logceil(ll x) { return x?8*sizeof(ll)-__builtin_clzll(x):0; }

namespace std { template<typename T,typename U>struct hash<pair<T,U>>{hash<T>t;hash<U>u;size_t operator()(const pair<T,U>&p)const{return t(p.x)^(u(p.y)<<7);}}; }
template<typename T,typename F>T bsh(T l,T h,const F&f){T r=-1,m;while(l<=h){m=(l+h)/2;if(f(m)){l=m+1;r=m;}else{h=m-1;}}return r;}
template<typename F> double bshd(double l,double h,const F&f,double p=1e-9){ui r=3+(ui)log2((h-l)/p);while(r--){double m=(l+h)/2;if(f(m)){l=m;}else{h=m;}}return (l+h)/2;}
template<typename T,typename F>T bsl(T l,T h,const F&f){T r=-1,m;while(l<=h){m=(l+h)/2;if(f(m)){h=m-1;r=m;}else{l=m+1;}}return r;}
template<typename F> double bsld(double l,double h,const F&f,double p=1e-9){ui r=3+(ui)log2((h-l)/p);while(r--){double m=(l+h)/2;if(f(m)){h=m;}else{l=m;}}return (l+h)/2;}
template<typename T> T gcd(T a,T b) { if (a<b) swap(a,b); return b?gcd(b,a%b):a; }

template<typename T>class vector2:public vector<vector<T>>{public:vector2(){} vector2(size_t a,size_t b,T t=T()):vector<vector<T>>(a,vector<T>(b,t)){}};
template<typename T>class vector3:public vector<vector2<T>>{public:vector3(){} vector3(size_t a,size_t b,size_t c,T t=T()):vector<vector2<T>>(a,vector2<T>(b,c,t)){}};
template<typename T>class vector4:public vector<vector3<T>>{public:vector4(){} vector4(size_t a,size_t b,size_t c,size_t d,T t=T()):vector<vector3<T>>(a,vector3<T>(b,c,d,t)){}};
template<typename T>class vector5:public vector<vector4<T>>{public:vector5(){} vector5(size_t a,size_t b,size_t c,size_t d,size_t e,T t=T()):vector<vector4<T>>(a,vector4<T>(b,c,d,e,t)){}};

#endif

class HNumberOfComponents {
public:
    int N, Q;
    vector<int> A;

    void build(vector<pii>&block, int from, int to) {
        block.clear();
        for (int i = from; i < to; ++i) {
            pii c = {A[i],A[i]};
            while (!block.empty() && block.back().x < c.y) {
                c = {min(block.back().x, c.x), max(block.back().y, c.y)};
                block.pop_back();
            }
            block.push_back(c);
        }
    }

    vector<vector<pii>> Blocks;

    struct BlockGroup {
        int blockId;
        int from, to;
        int lo, hi;
    };

    void solve(istream& cin, ostream& cout) {
        cin >> N >> Q;
        A.resize(N);
        cin >> A;

        int S = 2000;
        int B = (N+S-1)/S;
        Blocks.resize(B);
        for (int i = 0; i < B; ++i) {
            build(Blocks[i], i*S, min(i*S+S, N));
        }
        for (int q = 0; q < Q; ++q) {
            int p, x; cin >> p >> x;
            --p;
            int b = p/S;
            A[p] = x;
            build(Blocks[b], b*S, min(N, b*S+S));

            vector<BlockGroup> Groups;
            for (int i = 0; i < B; ++i) {

                auto &block = Blocks[i];
                int j = bsh(0, (int)block.size()-1, [&](int x) { return !Groups.empty() && Groups.back().lo < block[x].y; });
                if (j == -1) {
                    Groups.push_back(BlockGroup{i, 0, (int)block.size(), block.back().x, block[0].y});
                } else {
                    BlockGroup BG{-1, 0, 1, block.back().x, block[0].y};
                    while (!Groups.empty() && Groups.back().lo < BG.hi) {
                        auto &last = Groups.back();
                        if (last.blockId == -1) {
                            BG.lo = min(BG.lo, last.lo);
                            BG.hi = max(BG.hi, last.hi);
                            Groups.pop_back();
                        } else {
                            auto &lastB = Blocks[last.blockId];
                            if (lastB[last.from].x < BG.hi) {
                                BG.lo = min(BG.lo, last.lo);
                                BG.hi = max(BG.hi, last.hi);
                                Groups.pop_back();
                            } else {
                                int s = bsl(last.from, last.to - 1, [&](int x) { return lastB[x].x < BG.hi; });
                                last.lo = 1000000000;
                                last.hi = 0;

                                for (int k = last.from; k < s; ++k) {
                                    last.lo = min(last.lo, lastB[k].x);
                                    last.hi = max(last.hi, lastB[k].y);
                                }

                                for (int k = s; k < last.to; ++k) {
                                    BG.lo = min(BG.lo, lastB[k].x);
                                    BG.hi = max(BG.hi, lastB[k].y);
                                }
                                last.to = s;
                            }
                        }
                    }
                    Groups.push_back(BG);
                    if (j+1 != (int)block.size()) {
                        Groups.push_back(BlockGroup{i, j+1, (int)block.size(), block.back().x, block[j+1].y});
                    }
                }
            }

            int ans = 0;
            for (BlockGroup&bg: Groups) ans += bg.to - bg.from;
            cout << ans << '\n';
        }
    }
};

int main() {
	ios_base::sync_with_stdio(false); cin.tie(nullptr); cout.tie(nullptr);
	HNumberOfComponents solver;
	std::istream& in(std::cin);
	std::ostream& out(std::cout);
	solver.solve(in, out);
    return 0;
}


#pragma GCC optimize("Ofast")
#pragma GCC target("sse,sse2,sse3,ssse3,sse4,popcnt,abm,mmx,avx,tune=native")
#pragma GCC optimize("unroll-loops")
#include<bits/stdc++.h>
//#define int long long
using namespace std;

#define rep(i,n) for (int i=0;i<(int)(n);++i)
#define rep1(i,n) for (int i=1;i<=(int)(n);++i)
#define range(x) begin(x), end(x)
#define sz(x) (int)(x).size()
#define pb push_back
#define F first
#define S second

typedef long long ll;
typedef unsigned long long ull;
typedef long double ld;
typedef pair<int, int> pii;
typedef vector<int> vi;

namespace basics{
int ceil_pow2(int n) {
    int x = 0;
    while ((1U << x) < (unsigned int)(n)) x++;
    return x;
}

// @param n `1 <= n`
// @return minimum non-negative `x` s.t. `(n & (1 << x)) != 0`
int bsf(unsigned int n) {
#ifdef _MSC_VER
    unsigned long index;
    _BitScanForward(&index, n);
    return index;
#else
    return __builtin_ctz(n);
#endif
}

/*
计算u^v % mod
*/
ll power(ll u,ll v,ll mod){
    ll ret=1,t=u%mod;
    while (v){
        if (v&1) ret=t*ret%mod;
        t=t*t%mod, v>>=1;
    }
    return ret%mod;
}

/*
计算gcd(a,b)并找寻ax+by=gcd(a,b)的一组解
ret=exgcd(a,b,x,y);
*/
ll exgcd(ll a,ll b,ll &x,ll &y){
    if (b){
        ll d=exgcd(b,a%b,y,x);
        return y-=a/b*x, d;
    }
    return x=1,y=0,a;
}

/*
计算x=a(mod m), x=b(mod n)的一组解，若无解返回-1
ret=crt(a,m,b,n);
*/
ll crt(ll a,ll m,ll b,ll n){
    if (n>m) swap(a,b), swap(n,m);
    ll x,y,g=exgcd(m,n,x,y);
    if ((b-a)%g) return -1;
    x=(b-a)%n*x%n/g*m+a;
    return x<0?x+m*n/g:x;
}

/*
生成<=n的质数
gen_prime<5000>(ret);
*/

void gen_prime(int n,vi &ret){
    vector<bool> p;
    p.resize(n+1,1);
    p[0]=p[1]=0;
    for (int i=4;i<=n;i+=2) p[i]=0;
    for (int i=3;i*i<=n;i+=2){
        if (p[i]){
            for (int j=i*i;j<=n;j+=2*i){
                p[j]=0;
            }
        }
    }
    for (int i=2;i<=n;++i){
        if (p[i]) ret.pb(i);
    }
}

/*
生成<=n的phi
gen_phi<5000>(ret);
*/
void gen_phi(int n,vi &phi){
    phi.resize(n+1);
    for (int i=0;i<=n;++i) phi[i]=i&1?i:i/2;
    for (int i=3;i<=n;i+=2){
        if (phi[i]==i){
            for (int j=i;j<=n;j+=i) phi[j]-=phi[j]/i;
        }
    }
}

/*
支持更高的快速幂操作
expower.mod_pow(a,b,mod);
*/

struct expower{
    ull mod_mul(ull a,ull b,ull M) {
        ll ret=a*b-M*ull(ld(a)* ld(b)/ld(M));
        return ret+M*(ret<0)-M*(ret>=(ll)M);
    }
    ull mod_pow(ull b,ull e,ull mod) {
        ull ans=1;
        for (; e; b=mod_mul(b,b,mod), e/=2)
            if (e&1) ans=mod_mul(ans,b,mod);
        return ans%mod;
    }
}expower;

/*
Miller-Rubin素数判别
is_prime(n);
*/
bool is_prime(ull n){
    if (n<2||n%6%4!=1) return n-2<2;
    ull A[]={2,325,9375,28178,450775,9780504,1795265022},
    s=__builtin_ctzll(n-1), d = n >> s;
    for (auto a:A){
        ull p=expower.mod_pow(a,d,n),i=s;
        while (p!=1&&p!=n-1&&a%n&&i--)
            p=expower.mod_mul(p,p,n);
        if (p!=n-1&&i!=s) return 0;
    }
    return 1;
}

/*
素因数分解
ret=factorization(n);
*/
ull pollard(ull n){
    auto f=[n](ull x){return (expower.mod_mul(x,x,n)+1)%n;};
    if (!(n&1)) return 2;
    for (ull i=2;;i++){
        ull x=i,y=f(x),p;
        while ((p=__gcd(n+y-x,n))==1)
            x=f(x),y=f(f(y));
        if (p!=n) return p;
    }
}

vector<ull> factorization(ull n){
    if (n==1) return {};
    if (is_prime(n)) return {n};
    ull x=pollard(n);
    auto l=factorization(x),r=factorization(n/x);
    l.insert(l.end(),range(r));
    return l;
}
} // namespace basics

 /*
 并查集
 序号为0,1,...,n-1
 */
struct DSU{
    //insert info.
    vector<int> p;
    DSU(int n){
        p.resize(n);
        for (int i=1;i<n;++i) p[i]=i;
    }
    int find(int u){
        if (p[u]==u) return u;
        return p[u]=find(find(p[u]));
    }
    bool unite(int u,int v){
        int pu=find(u), pv=find(v);
        if (pu!=pv){
            p[pu]=pv;
        }
        return pu!=pv;
    }
};

/* (u,v,w) */
template<class T> struct MST{
    vector<tuple<int,int,T> > solve_detail(int n,vector<tuple<int,int,T> >g){
        vector<tuple<int,int,T> > ret;
        ret.clear();
        DSU dsu(n);
        auto cmp=[&](tuple<int,int,T> x,tuple<int,int,T> y){
            int ux,uy,vx,vy;
            T wx,wy;
            tie(ux,vx,wx)=x, tie(uy,vy,wy)=y;
            return wx<wy;
        };
        sort(range(g),cmp);
        for (auto c:g){
            int u,v;
            T w;
            tie(u,v,w)=c;
            if(dsu.unite(u,v)) ret.push_back(c);
        }
        return ret;
    }
    T solve(int n,vector<tuple<int,int,T> > &g){
        auto ret=solve_detail(n,g);
        T res=0;
        for (auto c:ret){
            int a,b;
            T d;
            tie(a,b,d)=c;
            res+=d;
        }
        return res;
    }
};

/*
copy from Atcoder library:
    construct: lazy_segtree<S,op,e,F,mapping,composition,id>
    usage: apply(l,r,f), max_left/right(l,g), set(p,x), get(p), prod(l,r) (inclusive,exclusive)
*/
template <class S,
          S (*op)(S, S),
          S (*e)(),
          class F,
          S (*mapping)(F, S),
          F (*composition)(F, F),
          F (*id)()>
struct lazy_segtree {
  public:
    lazy_segtree() : lazy_segtree(0) {}
    lazy_segtree(int n) : lazy_segtree(std::vector<S>(n, e())) {}
    lazy_segtree(const std::vector<S>& v) : _n(sz(v)) {
        log = basics::ceil_pow2(_n);
        size = 1 << log;
        d = std::vector<S>(2 * size, e());
        lz = std::vector<F>(size, id());
        for (int i = 0; i < _n; i++) d[size + i] = v[i];
        for (int i = size - 1; i >= 1; i--) {
            update(i);
        }
    }

    void set(int p, S x) {
        assert(0 <= p && p < _n);
        p += size;
        for (int i = log; i >= 1; i--) push(p >> i);
        d[p] = x;
        for (int i = 1; i <= log; i++) update(p >> i);
    }

    S get(int p) {
        assert(0 <= p && p < _n);
        p += size;
        for (int i = log; i >= 1; i--) push(p >> i);
        return d[p];
    }

    S prod(int l, int r) {
        assert(0 <= l && l <= r && r <= _n);
        if (l == r) return e();

        l += size;
        r += size;

        for (int i = log; i >= 1; i--) {
            if (((l >> i) << i) != l) push(l >> i);
            if (((r >> i) << i) != r) push(r >> i);
        }

        S sml = e(), smr = e();
        while (l < r) {
            if (l & 1) sml = op(sml, d[l++]);
            if (r & 1) smr = op(d[--r], smr);
            l >>= 1;
            r >>= 1;
        }

        return op(sml, smr);
    }

    S all_prod() { return d[1]; }

    void apply(int p, F f) {
        assert(0 <= p && p < _n);
        p += size;
        for (int i = log; i >= 1; i--) push(p >> i);
        d[p] = mapping(f, d[p]);
        for (int i = 1; i <= log; i++) update(p >> i);
    }
    void apply(int l, int r, F f) {
        assert(0 <= l && l <= r && r <= _n);
        if (l == r) return;

        l += size;
        r += size;

        for (int i = log; i >= 1; i--) {
            if (((l >> i) << i) != l) push(l >> i);
            if (((r >> i) << i) != r) push((r - 1) >> i);
        }

        {
            int l2 = l, r2 = r;
            while (l < r) {
                if (l & 1) all_apply(l++, f);
                if (r & 1) all_apply(--r, f);
                l >>= 1;
                r >>= 1;
            }
            l = l2;
            r = r2;
        }

        for (int i = 1; i <= log; i++) {
            if (((l >> i) << i) != l) update(l >> i);
            if (((r >> i) << i) != r) update((r - 1) >> i);
        }
    }

    template <bool (*g)(S)> int max_right(int l) {
        return max_right(l, [](S x) { return g(x); });
    }
    template <class G> int max_right(int l, G g) {
        assert(0 <= l && l <= _n);
        assert(g(e()));
        if (l == _n) return _n;
        l += size;
        for (int i = log; i >= 1; i--) push(l >> i);
        S sm = e();
        do {
            while (l % 2 == 0) l >>= 1;
            if (!g(op(sm, d[l]))) {
                while (l < size) {
                    push(l);
                    l = (2 * l);
                    if (g(op(sm, d[l]))) {
                        sm = op(sm, d[l]);
                        l++;
                    }
                }
                return l - size;
            }
            sm = op(sm, d[l]);
            l++;
        } while ((l & -l) != l);
        return _n;
    }

    template <bool (*g)(S)> int min_left(int r) {
        return min_left(r, [](S x) { return g(x); });
    }
    template <class G> int min_left(int r, G g) {
        assert(0 <= r && r <= _n);
        assert(g(e()));
        if (r == 0) return 0;
        r += size;
        for (int i = log; i >= 1; i--) push((r - 1) >> i);
        S sm = e();
        do {
            r--;
            while (r > 1 && (r % 2)) r >>= 1;
            if (!g(op(d[r], sm))) {
                while (r < size) {
                    push(r);
                    r = (2 * r + 1);
                    if (g(op(d[r], sm))) {
                        sm = op(d[r], sm);
                        r--;
                    }
                }
                return r + 1 - size;
            }
            sm = op(d[r], sm);
        } while ((r & -r) != r);
        return 0;
    }

  private:
    int _n, size, log;
    std::vector<S> d;
    std::vector<F> lz;

    void update(int k) { d[k] = op(d[2 * k], d[2 * k + 1]); }
    void all_apply(int k, F f) {
        d[k] = mapping(f, d[k]);
        if (k < size) lz[k] = composition(f, lz[k]);
    }
    void push(int k) {
        all_apply(2 * k, lz[k]);
        all_apply(2 * k + 1, lz[k]);
        lz[k] = id();
    }
};

struct XORBasis{
    int n;
    vector<ull> p;
    vector<ull> ans;
    XORBasis(int k):n(k){
        p.resize(k+1);
    }
    void rebuilt(){
        ans.clear();
        for (int i=0;i<=n;++i){
            if (p[i]) ans.push_back(p[i]);
        }
    }
    void insert(ull u){
        for (int i=n;i>=0;--i){
            if (u&(1ull<<i)){
                if (p[i]) u^=p[i];
                else{
                    p[i]=u;
                    for (int j=i-1;j>=0;--j){
                        if (p[i]&(1ull<<j)) p[i]^=p[j];
                    }
                    for (int j=i+1;j<=n;++j){
                        if (p[j]&(1ull<<i)) p[j]^=p[i];
                    }
                    break;
                }
            }
        }
        rebuilt();
    }
    bool check(ull u){
        for (int i=n;i>-1;--i){
            if (u&(1ull<<i)) u^=p[i];
        }
        return (u==0);
    }
    ull kth(ull t){ // the k-th smallest, excluding 0.
        if (t>=(1ull<<sz(ans))) return -1;
        ull ret=0;
        for (int i=0;i<sz(ans);++i){
            if (t&(1ull<<i)) ret^=ans[i];
        }
        return ret;
    }
    ull total(){
        return (1ull<<sz(ans));
    }
};

/*
pi: gen vector pi for string s
match: find out all possible matches for pattern pat
*/

struct KMP{
    vi pi(const string& s) {
	    vi p(sz(s));
	    for (int i=1;i<=sz(s);++i) {
	    	int g = p[i-1];
	    	while (g && s[i] != s[g]) g = p[g-1];
	    	p[i] = g + (s[i] == s[g]);
    	}
	    return p;
    }

    vi match(const string& s, const string& pat) {
	    vi p = pi(pat + '\0' + s), res;
	    for(int i=sz(p)-sz(s);i<=sz(p);++i)
	    	if (p[i] == sz(pat)) res.push_back(i - 2 * sz(pat));
	    return res;
    }
};

struct AhoCorasick {
	enum {alpha = 26, first = 'a'};
	struct Node {
		// (nmatches is optional)
		int back, next[alpha], start = -1, end = -1;
        ll nmatches = 0;
		Node(int v) { memset(next, v, sizeof(next)); }
	};
	vector<Node> N;
	vector<int> backp;
	void insert(string& s, int j,ll val) {
		assert(!s.empty());
		int n = 0;
		for(auto c:s) {
			int& m = N[n].next[c - first];
			if (m == -1) { n = m = sz(N); N.emplace_back(-1); }
			else n = m;
		}
		if (N[n].end == -1) N[n].start = j;
		backp.push_back(N[n].end);
		N[n].end = j;
		N[n].nmatches+=val;
	}
	AhoCorasick(vector<string>& pat,vi val) {
		N.emplace_back(-1);
		for (int i=0;i<sz(pat);++i) insert(pat[i], i, val[i]);
		N[0].back = sz(N);
		N.emplace_back(0);

		queue<int> q;
		for (q.push(0); !q.empty(); q.pop()) {
			int n = q.front(), prev = N[n].back;
			for (int i=0;i<alpha;++i) {
				int &ed = N[n].next[i], y = N[prev].next[i];
				if (ed == -1) ed = y;
				else {
					N[ed].back = y;
					(N[ed].end == -1 ? N[ed].end : backp[N[ed].start])
						= N[y].end;
					N[ed].nmatches += N[y].nmatches;
					q.push(ed);
				}
			}
		}
	}
	vi find(string& word,ll& ans) {
		int n = 0;
		vi res;
		for(auto c:word) {
			n = N[n].next[c - first];
			res.push_back(N[n].end);
			ans += N[n].nmatches;
		}
		return res;
	}
	vector<vi> findAll(vector<string>& pat, string word) {
		ll ans=0;
        vi r = find(word,ans);
		vector<vi> res(sz(word));
		for (int i=0;i<sz(word);++i) {
			int ind = r[i];
			while (ind != -1) {
				res[i - sz(pat[ind]) + 1].push_back(ind);
				ind = backp[ind];
			}
		}
		return res;
	}
};

struct HLD{
    int n,cnt=0;
    vector<vi> G;
    vi par,dep,siz,son,top,dfn,rk;
    //父亲节点，深度，子树大小，重子节点，重链头部，dfs序，dfs序对应的节点编号
    HLD(vector<vi> g,int root=1):n(sz(g)),G(g),par(n+7),dep(n+7),siz(n+7,1),son(n+7,-1),top(n+7),dfn(n+7),rk(n+7){
        dep[0]=-1, dfs1(root,0), dfs2(root,0,root);
    }
    void dfs1(int u,int p){
        for (auto c:G[u]){
            if (c==p) continue;
            dep[c]=dep[u]+1, par[c]=u;
            dfs1(c,u);
            siz[u]+=siz[c];
            if (son[u]==-1||siz[son[u]]<siz[c]) son[u]=c;
        }
    }
    void dfs2(int u,int p,int tp){
        top[u]=tp;
        dfn[u]=++cnt;
        rk[cnt]=u;
        if (son[u]==-1) return;
        dfs2(son[u],u,tp);
        for (auto c:G[u]){
            if (c==p||c==son[u]) continue;
            dfs2(c,u,c);
        }
    }
    int lca(int u,int v){
        while (top[u]!=top[v]){
            if (dep[top[u]]>dep[top[v]]){
                u=par[top[u]];
            }
            else{
                v=par[top[v]];
            }
        }
        return dep[u]>dep[v]?v:u;
    }
    vector<pii> find_seg(int u,int v){
        vector<pii> ft,bk,res;
        ft.clear(), bk.clear(), res.clear();
//        cout<<top[u]<<" "<<top[v]<<endl;
        while (top[u]!=top[v]){
            if (dep[top[u]]>dep[top[v]]){
                ft.pb({u,top[u]});
                u=par[top[u]];
            }
            else{
                bk.pb({top[v],v});
                v=par[top[v]];
            }
        }
        ft.pb({u,v});
        for (int i=0;i<sz(ft);++i) res.pb(ft[i]);
        for (int i=sz(bk);i>0;--i) res.pb(bk[i-1]);
        return res;
    }
};

struct BIT{
    vi C; int n;
    BIT(int n):n(n){C.resize(n+7,0);}
    void update(int u,int w){
        for (;u<=n;u+=u&(-u)) C[u]+=w;
    }
    int query(int u){
        int res=0;
        for (;u>0;u-=u&(-u)) res+=C[u];
        return res;
    }
};

vi topoSort(const vector<vi>& gr) {
	vi indeg(sz(gr)), ret;
	for (auto& li : gr) for (int x : li) indeg[x]++;
	queue<int> q; // use priority queue for lexic. smallest ans.
	rep(i,sz(gr)) if (indeg[i] == 0) q.push(-i);
	while (!q.empty()) {
		int i = -q.front(); // top() for priority queue
		ret.push_back(i);
		q.pop();
		for (int x : gr[i])
			if (--indeg[x] == 0) q.push(-x);
	}
	return ret;
}

struct Eulerian{
  public:
    Eulerian(int n,int m):_n(n),_m(m){
        path.clear();
        _g.resize(n,vector<pii>(0));
        pt.resize(n,0);
        vis.resize(m,0);
        deg.resize(n,0);
    }
    void add(int x,int y,int id){
        _g[x].pb({y,id});
        pt[x]++;
        nxt=x;
        deg[y]++;
    }
    bool solve(){
        rep(i,_n) if (deg[i]&1) return false;
        dfs(nxt);
        if (sz(path)<_m) return 0;
        return true;
    }
    vi solve_path(){
        if (!solve()) path.clear();
        reverse(range(path));
        return path;
    }
  private:
    int _n,_m,nxt;
    vi path;
    vector<vector<pii>> _g;
    vi pt;
    vi deg;
    vector<bool> vis;
    int abs(int u){
        if (u<0) return ~u;
        return u;
    }
    void dfs(int u){
        while (pt[u]){
            while (pt[u]&&vis[abs(_g[u][pt[u]-1].S)]) pt[u]--;
            if (!pt[u]) break;
            int to=_g[u][pt[u]-1].F, id=_g[u][pt[u]-1].S;
            vis[abs(id)]=1;
            dfs(to), path.pb(id);
        }
    }
};

template<class T> struct FWT{
  public:
    vector<T> OR(vector<T> &a){
        return _OR(a,1);
    }
    vector<T> ROR(vector<T> &a){
        return _OR(a,-1);
    }
    vector<T> AND(vector<T> &a){
        return _AND(a,1);
    }
    vector<T> RAND(vector<T> &a){
        return _AND(a,-1);
    }
    vector<T> XOR(vector<T> &a){
        return _XOR(a,1);
    }
    vector<T> RXOR(vector<T> &a){
        return _XOR(a,-1);
    }
  private:
    vector<T> _OR(vector<T> &a,int mode=1){
        vector<T> b(a);
        for (int i=0;(1<<i)<sz(a);++i){
            for (int j=0;j<sz(a);++j){
                if (j>>i&1) b[j]+=b[j^(1<<i)]*mode;
            }
        }
        return b;
    }
    vector<T> _AND(vector<T> &a,int mode=1){
        vector<T> b(a);
        for (int i=0;(1<<i)<sz(a);++i){
            for (int j=0;j<sz(a);++j){
                if (j>>i&1) b[j^(1<<i)]+=b[j]*mode;
            }
        }
        return b;
    }
    vector<T> _XOR(vector<T> &a,int mode=1){
        vector<T> b(a);
        for (int i=0;(1<<i)<sz(a);++i){
            for (int j=0;j<sz(a);++j){
                if (j>>i&1){
                    b[j^(1<<i)]+=b[j];
                    b[j]=b[j^(1<<i)]-2*b[j];
                    if (mode<0) b[j]/=2, b[j^(1<<i)]/=2;
                }
            }
        }
        return b;
    }
};

/* atcoder mincost-maxflow */

template <class Cap, class Cost> struct mcf_graph {
  public:
    mcf_graph() {}
    mcf_graph(int n) : _n(n), g(n) {}

    int add_edge(int from, int to, Cap cap, Cost cost) {
        assert(0 <= from && from < _n);
        assert(0 <= to && to < _n);
        int m = (int)(pos.size());
        pos.push_back({from, (int)(g[from].size())});
        g[from].push_back(_edge{to, (int)(g[to].size()), cap, cost});
        g[to].push_back(_edge{from, (int)(g[from].size()) - 1, 0, -cost});
        return m;
    }

    struct edge {
        int from, to;
        Cap cap, flow;
        Cost cost;
    };

    edge get_edge(int i) {
        int m = (int)(pos.size());
        assert(0 <= i && i < m);
        auto _e = g[pos[i].first][pos[i].second];
        auto _re = g[_e.to][_e.rev];
        return edge{
            pos[i].first, _e.to, _e.cap + _re.cap, _re.cap, _e.cost,
        };
    }
    std::vector<edge> edges() {
        int m = (int)(pos.size());
        std::vector<edge> result(m);
        for (int i = 0; i < m; i++) {
            result[i] = get_edge(i);
        }
        return result;
    }

    std::pair<Cap, Cost> flow(int s, int t) {
        return flow(s, t, std::numeric_limits<Cap>::max());
    }
    std::pair<Cap, Cost> flow(int s, int t, Cap flow_limit) {
        return slope(s, t, flow_limit).back();
    }
    std::vector<std::pair<Cap, Cost>> slope(int s, int t) {
        return slope(s, t, std::numeric_limits<Cap>::max());
    }
    std::vector<std::pair<Cap, Cost>> slope(int s, int t, Cap flow_limit) {
        assert(0 <= s && s < _n);
        assert(0 <= t && t < _n);
        assert(s != t);
        // variants (C = maxcost):
        // -(n-1)C <= dual[s] <= dual[i] <= dual[t] = 0
        // reduced cost (= e.cost + dual[e.from] - dual[e.to]) >= 0 for all edge
        std::vector<Cost> dual(_n, 0), dist(_n);
        std::vector<int> pv(_n), pe(_n);
        std::vector<bool> vis(_n);
        auto dual_ref = [&]() {
            std::fill(dist.begin(), dist.end(),
                      std::numeric_limits<Cost>::max());
            std::fill(pv.begin(), pv.end(), -1);
            std::fill(pe.begin(), pe.end(), -1);
            std::fill(vis.begin(), vis.end(), false);
            struct Q {
                Cost key;
                int to;
                bool operator<(Q r) const { return key > r.key; }
            };
            std::priority_queue<Q> que;
            dist[s] = 0;
            que.push(Q{0, s});
            while (!que.empty()) {
                int v = que.top().to;
                que.pop();
                if (vis[v]) continue;
                vis[v] = true;
                if (v == t) break;
                // dist[v] = shortest(s, v) + dual[s] - dual[v]
                // dist[v] >= 0 (all reduced cost are positive)
                // dist[v] <= (n-1)C
                for (int i = 0; i < (int)(g[v].size()); i++) {
                    auto e = g[v][i];
                    if (vis[e.to] || !e.cap) continue;
                    // |-dual[e.to] + dual[v]| <= (n-1)C
                    // cost <= C - -(n-1)C + 0 = nC
                    Cost cost = e.cost - dual[e.to] + dual[v];
                    if (dist[e.to] - dist[v] > cost) {
                        dist[e.to] = dist[v] + cost;
                        pv[e.to] = v;
                        pe[e.to] = i;
                        que.push(Q{dist[e.to], e.to});
                    }
                }
            }
            if (!vis[t]) {
                return false;
            }

            for (int v = 0; v < _n; v++) {
                if (!vis[v]) continue;
                // dual[v] = dual[v] - dist[t] + dist[v]
                //         = dual[v] - (shortest(s, t) + dual[s] - dual[t]) + (shortest(s, v) + dual[s] - dual[v])
                //         = - shortest(s, t) + dual[t] + shortest(s, v)
                //         = shortest(s, v) - shortest(s, t) >= 0 - (n-1)C
                dual[v] -= dist[t] - dist[v];
            }
            return true;
        };
        Cap flow = 0;
        Cost cost = 0, prev_cost = -1;
        std::vector<std::pair<Cap, Cost>> result;
        result.push_back({flow, cost});
        while (flow < flow_limit) {
            if (!dual_ref()) break;
            Cap c = flow_limit - flow;
            for (int v = t; v != s; v = pv[v]) {
                c = std::min(c, g[pv[v]][pe[v]].cap);
            }
            for (int v = t; v != s; v = pv[v]) {
                auto& e = g[pv[v]][pe[v]];
                e.cap -= c;
                g[v][e.rev].cap += c;
            }
            Cost d = -dual[s];
            flow += c;
            cost += c * d;
            if (prev_cost == d) {
                result.pop_back();
            }
            result.push_back({flow, cost});
            prev_cost = cost;
        }
        return result;
    }

  private:
    int _n;

    struct _edge {
        int to, rev;
        Cap cap;
        Cost cost;
    };

    std::vector<std::pair<int, int>> pos;
    std::vector<std::vector<_edge>> g;
};

struct S{
    int act,inact,mn;
};

using F = int;

S e(){
    return {0,0,1000*1000+6};
}

S op(S l,S r){
    if (l.mn==r.mn) return {l.act+r.act,l.inact+r.inact,l.mn};
    if (l.mn<r.mn) return{l.act,l.inact,l.mn};
    else return {r.act,r.inact,r.mn};
}

F id(){
    return 0;
}

S mapping(F l,S r){
    return {r.act,r.inact,r.mn+l};
}

F composition(F l,F r){
    return l+r;
}

const int maxn=500007;
lazy_segtree<S,op,e,F,mapping,composition,id> seg(1e6+10);
int n,q;
int a[maxn];
signed main(){
    ios::sync_with_stdio(false);
    cin.tie(0), cout.tie(0);
    cin>>n>>q;
    a[0]=1e6+5;
    rep1(i,1e6) seg.set(i,{0,1,0});
    rep1(i,n){
        cin>>a[i];
        if (a[i]>a[i-1]) seg.apply(a[i-1]+1,a[i]+1,1);
        else seg.apply(a[i]+1,a[i-1]+1,1);
        auto f=seg.get(a[i]);
        swap(f.act,f.inact);
        seg.set(a[i],f);
    }
    seg.apply(1,a[n]+1,1);
    while (q--){
        int pos,x;
        cin>>pos>>x;
        int prev=a[pos];
        auto ret=seg.get(a[pos]);
        swap(ret.act,ret.inact);
        seg.set(a[pos],ret);
        ret=seg.get(x);
        swap(ret.act,ret.inact);
        seg.set(x,ret);
        a[pos]=x;
        auto update=[&](int l,int r,int w){
//            cout<<l<<" "<<r<<" "<<w<<endl;
            if (l>r) swap(l,r);
            seg.apply(l+1,r+1,w);
        };
        update(a[pos-1],prev,-1);
        update(a[pos-1],x,1);
        update(a[pos+1],prev,-1);
        update(a[pos+1],x,1);
        ret=seg.prod(1,1e6+1);
        if (ret.mn<=1){
            assert(ret.mn==1);
            cout<<ret.act<<" ";
        }
        else cout<<0<<" ";
    }
    return 0;
}


//#pragma GCC optimize("Ofast")
//#pragma GCC target("sse,sse2,sse3,ssse3,sse4,popcnt,abm,mmx,avx,tune=native")
//#pragma GCC optimize("unroll-loops")
#include<bits/stdc++.h>
#define int long long
using namespace std;

#define rep(i,n) for (int i=0;i<(int)(n);++i)
#define rep1(i,n) for (int i=1;i<=(int)(n);++i)
#define range(x) begin(x), end(x)
#define sz(x) (int)(x).size()
#define pb push_back
#define F first
#define S second

typedef long long ll;
typedef unsigned long long ull;
typedef long double ld;
typedef pair<int, int> pii;
typedef vector<int> vi;

namespace basics{
int ceil_pow2(int n) {
    int x = 0;
    while ((1U << x) < (unsigned int)(n)) x++;
    return x;
}

// @param n `1 <= n`
// @return minimum non-negative `x` s.t. `(n & (1 << x)) != 0`
int bsf(unsigned int n) {
#ifdef _MSC_VER
    unsigned long index;
    _BitScanForward(&index, n);
    return index;
#else
    return __builtin_ctz(n);
#endif
}

/*
计算u^v % mod
*/
ll power(ll u,ll v,ll mod){
    ll ret=1,t=u%mod;
    while (v){
        if (v&1) ret=t*ret%mod;
        t=t*t%mod, v>>=1;
    }
    return ret%mod;
}

/*
计算gcd(a,b)并找寻ax+by=gcd(a,b)的一组解
ret=exgcd(a,b,x,y);
*/
ll exgcd(ll a,ll b,ll &x,ll &y){
    if (b){
        ll d=exgcd(b,a%b,y,x);
        return y-=a/b*x, d;
    }
    return x=1,y=0,a;
}

/*
计算x=a(mod m), x=b(mod n)的一组解，若无解返回-1
ret=crt(a,m,b,n);
*/
ll crt(ll a,ll m,ll b,ll n){
    if (n>m) swap(a,b), swap(n,m);
    ll x,y,g=exgcd(m,n,x,y);
    if ((b-a)%g) return -1;
    x=(b-a)%n*x%n/g*m+a;
    return x<0?x+m*n/g:x;
}

/*
生成<=n的质数
gen_prime<5000>(ret);
*/

void gen_prime(int n,vi &ret){
    vector<bool> p;
    p.resize(n+1,1);
    p[0]=p[1]=0;
    for (int i=4;i<=n;i+=2) p[i]=0;
    for (int i=3;i*i<=n;i+=2){
        if (p[i]){
            for (int j=i*i;j<=n;j+=2*i){
                p[j]=0;
            }
        }
    }
    for (int i=2;i<=n;++i){
        if (p[i]) ret.pb(i);
    }
}

/*
生成<=n的phi
gen_phi<5000>(ret);
*/
void gen_phi(int n,vi &phi){
    phi.resize(n+1);
    for (int i=0;i<=n;++i) phi[i]=i&1?i:i/2;
    for (int i=3;i<=n;i+=2){
        if (phi[i]==i){
            for (int j=i;j<=n;j+=i) phi[j]-=phi[j]/i;
        }
    }
}

/*
支持更高的快速幂操作
expower.mod_pow(a,b,mod);
*/

struct expower{
    ull mod_mul(ull a,ull b,ull M) {
        ll ret=a*b-M*ull(ld(a)* ld(b)/ld(M));
        return ret+M*(ret<0)-M*(ret>=(ll)M);
    }
    ull mod_pow(ull b,ull e,ull mod) {
        ull ans=1;
        for (; e; b=mod_mul(b,b,mod), e/=2)
            if (e&1) ans=mod_mul(ans,b,mod);
        return ans%mod;
    }
}expower;

/*
Miller-Rubin素数判别
is_prime(n);
*/
bool is_prime(ull n){
    if (n<2||n%6%4!=1) return n-2<2;
    ull A[]={2,325,9375,28178,450775,9780504,1795265022},
    s=__builtin_ctzll(n-1), d = n >> s;
    for (auto a:A){
        ull p=expower.mod_pow(a,d,n),i=s;
        while (p!=1&&p!=n-1&&a%n&&i--)
            p=expower.mod_mul(p,p,n);
        if (p!=n-1&&i!=s) return 0;
    }
    return 1;
}

/*
素因数分解
ret=factorization(n);
*/
ull pollard(ull n){
    auto f=[n](ull x){return (expower.mod_mul(x,x,n)+1)%n;};
    if (!(n&1)) return 2;
    for (ull i=2;;i++){
        ull x=i,y=f(x),p;
        while ((p=__gcd(n+y-x,n))==1)
            x=f(x),y=f(f(y));
        if (p!=n) return p;
    }
}

vector<ull> factorization(ull n){
    if (n==1) return {};
    if (is_prime(n)) return {n};
    ull x=pollard(n);
    auto l=factorization(x),r=factorization(n/x);
    l.insert(l.end(),range(r));
    return l;
}
} // namespace basics

 /*
 并查集
 序号为0,1,...,n-1
 */
struct DSU{
    //insert info.
    vector<int> p;
    DSU(int n){
        p.resize(n);
        for (int i=1;i<n;++i) p[i]=i;
    }
    int find(int u){
        if (p[u]==u) return u;
        return p[u]=find(find(p[u]));
    }
    bool unite(int u,int v){
        int pu=find(u), pv=find(v);
        if (pu!=pv){
            p[pu]=pv;
        }
        return pu!=pv;
    }
};

/* (u,v,w) */
template<class T> struct MST{
    vector<tuple<int,int,T> > solve_detail(int n,vector<tuple<int,int,T> >g){
        vector<tuple<int,int,T> > ret;
        ret.clear();
        DSU dsu(n);
        auto cmp=[&](tuple<int,int,T> x,tuple<int,int,T> y){
            int ux,uy,vx,vy;
            T wx,wy;
            tie(ux,vx,wx)=x, tie(uy,vy,wy)=y;
            return wx<wy;
        };
        sort(range(g),cmp);
        for (auto c:g){
            int u,v;
            T w;
            tie(u,v,w)=c;
            if(dsu.unite(u,v)) ret.push_back(c);
        }
        return ret;
    }
    T solve(int n,vector<tuple<int,int,T> > &g){
        auto ret=solve_detail(n,g);
        T res=0;
        for (auto c:ret){
            int a,b;
            T d;
            tie(a,b,d)=c;
            res+=d;
        }
        return res;
    }
};

/*
copy from Atcoder library:
    construct: lazy_segtree<S,op,e,F,mapping,composition,id>
    usage: apply(l,r,f), max_left/right(l,g), set(p,x), get(p), prod(l,r) (inclusive,exclusive)
*/
template <class S,
          S (*op)(S, S),
          S (*e)(),
          class F,
          S (*mapping)(F, S),
          F (*composition)(F, F),
          F (*id)()>
struct lazy_segtree {
  public:
    lazy_segtree() : lazy_segtree(0) {}
    lazy_segtree(int n) : lazy_segtree(std::vector<S>(n, e())) {}
    lazy_segtree(const std::vector<S>& v) : _n(sz(v)) {
        log = basics::ceil_pow2(_n);
        size = 1 << log;
        d = std::vector<S>(2 * size, e());
        lz = std::vector<F>(size, id());
        for (int i = 0; i < _n; i++) d[size + i] = v[i];
        for (int i = size - 1; i >= 1; i--) {
            update(i);
        }
    }

    void set(int p, S x) {
        assert(0 <= p && p < _n);
        p += size;
        for (int i = log; i >= 1; i--) push(p >> i);
        d[p] = x;
        for (int i = 1; i <= log; i++) update(p >> i);
    }

    S get(int p) {
        assert(0 <= p && p < _n);
        p += size;
        for (int i = log; i >= 1; i--) push(p >> i);
        return d[p];
    }

    S prod(int l, int r) {
        assert(0 <= l && l <= r && r <= _n);
        if (l == r) return e();

        l += size;
        r += size;

        for (int i = log; i >= 1; i--) {
            if (((l >> i) << i) != l) push(l >> i);
            if (((r >> i) << i) != r) push(r >> i);
        }

        S sml = e(), smr = e();
        while (l < r) {
            if (l & 1) sml = op(sml, d[l++]);
            if (r & 1) smr = op(d[--r], smr);
            l >>= 1;
            r >>= 1;
        }

        return op(sml, smr);
    }

    S all_prod() { return d[1]; }

    void apply(int p, F f) {
        assert(0 <= p && p < _n);
        p += size;
        for (int i = log; i >= 1; i--) push(p >> i);
        d[p] = mapping(f, d[p]);
        for (int i = 1; i <= log; i++) update(p >> i);
    }
    void apply(int l, int r, F f) {
        assert(0 <= l && l <= r && r <= _n);
        if (l == r) return;

        l += size;
        r += size;

        for (int i = log; i >= 1; i--) {
            if (((l >> i) << i) != l) push(l >> i);
            if (((r >> i) << i) != r) push((r - 1) >> i);
        }

        {
            int l2 = l, r2 = r;
            while (l < r) {
                if (l & 1) all_apply(l++, f);
                if (r & 1) all_apply(--r, f);
                l >>= 1;
                r >>= 1;
            }
            l = l2;
            r = r2;
        }

        for (int i = 1; i <= log; i++) {
            if (((l >> i) << i) != l) update(l >> i);
            if (((r >> i) << i) != r) update((r - 1) >> i);
        }
    }

    template <bool (*g)(S)> int max_right(int l) {
        return max_right(l, [](S x) { return g(x); });
    }
    template <class G> int max_right(int l, G g) {
        assert(0 <= l && l <= _n);
        assert(g(e()));
        if (l == _n) return _n;
        l += size;
        for (int i = log; i >= 1; i--) push(l >> i);
        S sm = e();
        do {
            while (l % 2 == 0) l >>= 1;
            if (!g(op(sm, d[l]))) {
                while (l < size) {
                    push(l);
                    l = (2 * l);
                    if (g(op(sm, d[l]))) {
                        sm = op(sm, d[l]);
                        l++;
                    }
                }
                return l - size;
            }
            sm = op(sm, d[l]);
            l++;
        } while ((l & -l) != l);
        return _n;
    }

    template <bool (*g)(S)> int min_left(int r) {
        return min_left(r, [](S x) { return g(x); });
    }
    template <class G> int min_left(int r, G g) {
        assert(0 <= r && r <= _n);
        assert(g(e()));
        if (r == 0) return 0;
        r += size;
        for (int i = log; i >= 1; i--) push((r - 1) >> i);
        S sm = e();
        do {
            r--;
            while (r > 1 && (r % 2)) r >>= 1;
            if (!g(op(d[r], sm))) {
                while (r < size) {
                    push(r);
                    r = (2 * r + 1);
                    if (g(op(d[r], sm))) {
                        sm = op(d[r], sm);
                        r--;
                    }
                }
                return r + 1 - size;
            }
            sm = op(d[r], sm);
        } while ((r & -r) != r);
        return 0;
    }

  private:
    int _n, size, log;
    std::vector<S> d;
    std::vector<F> lz;

    void update(int k) { d[k] = op(d[2 * k], d[2 * k + 1]); }
    void all_apply(int k, F f) {
        d[k] = mapping(f, d[k]);
        if (k < size) lz[k] = composition(f, lz[k]);
    }
    void push(int k) {
        all_apply(2 * k, lz[k]);
        all_apply(2 * k + 1, lz[k]);
        lz[k] = id();
    }
};

struct XORBasis{
    int n;
    vector<ull> p;
    vector<ull> ans;
    XORBasis(int k):n(k){
        p.resize(k+1);
    }
    void rebuilt(){
        ans.clear();
        for (int i=0;i<=n;++i){
            if (p[i]) ans.push_back(p[i]);
        }
    }
    void insert(ull u){
        for (int i=n;i>=0;--i){
            if (u&(1ull<<i)){
                if (p[i]) u^=p[i];
                else{
                    p[i]=u;
                    for (int j=i-1;j>=0;--j){
                        if (p[i]&(1ull<<j)) p[i]^=p[j];
                    }
                    for (int j=i+1;j<=n;++j){
                        if (p[j]&(1ull<<i)) p[j]^=p[i];
                    }
                    break;
                }
            }
        }
        rebuilt();
    }
    bool check(ull u){
        for (int i=n;i>-1;--i){
            if (u&(1ull<<i)) u^=p[i];
        }
        return (u==0);
    }
    ull kth(ull t){ // the k-th smallest, excluding 0.
        if (t>=(1ull<<sz(ans))) return -1;
        ull ret=0;
        for (int i=0;i<sz(ans);++i){
            if (t&(1ull<<i)) ret^=ans[i];
        }
        return ret;
    }
    ull total(){
        return (1ull<<sz(ans));
    }
};

/*
pi: gen vector pi for string s
match: find out all possible matches for pattern pat
*/

struct KMP{
    vi pi(const string& s) {
	    vi p(sz(s));
	    for (int i=1;i<=sz(s);++i) {
	    	int g = p[i-1];
	    	while (g && s[i] != s[g]) g = p[g-1];
	    	p[i] = g + (s[i] == s[g]);
    	}
	    return p;
    }

    vi match(const string& s, const string& pat) {
	    vi p = pi(pat + '\0' + s), res;
	    for(int i=sz(p)-sz(s);i<=sz(p);++i)
	    	if (p[i] == sz(pat)) res.push_back(i - 2 * sz(pat));
	    return res;
    }
};

struct AhoCorasick {
	enum {alpha = 26, first = 'a'};
	struct Node {
		// (nmatches is optional)
		int back, next[alpha], start = -1, end = -1;
        ll nmatches = 0;
		Node(int v) { memset(next, v, sizeof(next)); }
	};
	vector<Node> N;
	vector<int> backp;
	void insert(string& s, int j,ll val) {
		assert(!s.empty());
		int n = 0;
		for(auto c:s) {
			int& m = N[n].next[c - first];
			if (m == -1) { n = m = sz(N); N.emplace_back(-1); }
			else n = m;
		}
		if (N[n].end == -1) N[n].start = j;
		backp.push_back(N[n].end);
		N[n].end = j;
		N[n].nmatches+=val;
	}
	AhoCorasick(vector<string>& pat,vi val) {
		N.emplace_back(-1);
		for (int i=0;i<sz(pat);++i) insert(pat[i], i, val[i]);
		N[0].back = sz(N);
		N.emplace_back(0);

		queue<int> q;
		for (q.push(0); !q.empty(); q.pop()) {
			int n = q.front(), prev = N[n].back;
			for (int i=0;i<alpha;++i) {
				int &ed = N[n].next[i], y = N[prev].next[i];
				if (ed == -1) ed = y;
				else {
					N[ed].back = y;
					(N[ed].end == -1 ? N[ed].end : backp[N[ed].start])
						= N[y].end;
					N[ed].nmatches += N[y].nmatches;
					q.push(ed);
				}
			}
		}
	}
	vi find(string& word,ll& ans) {
		int n = 0;
		vi res;
		for(auto c:word) {
			n = N[n].next[c - first];
			res.push_back(N[n].end);
			ans += N[n].nmatches;
		}
		return res;
	}
	vector<vi> findAll(vector<string>& pat, string word) {
		ll ans=0;
        vi r = find(word,ans);
		vector<vi> res(sz(word));
		for (int i=0;i<sz(word);++i) {
			int ind = r[i];
			while (ind != -1) {
				res[i - sz(pat[ind]) + 1].push_back(ind);
				ind = backp[ind];
			}
		}
		return res;
	}
};

struct HLD{
    int n,cnt=0;
    vector<vi> G;
    vi par,dep,siz,son,top,dfn,rk;
    //父亲节点，深度，子树大小，重子节点，重链头部，dfs序，dfs序对应的节点编号
    HLD(vector<vi> g,int root=1):n(sz(g)),G(g),par(n+7),dep(n+7),siz(n+7,1),son(n+7,-1),top(n+7),dfn(n+7),rk(n+7){
        dep[0]=-1, dfs1(root,0), dfs2(root,0,root);
    }
    void dfs1(int u,int p){
        for (auto c:G[u]){
            if (c==p) continue;
            dep[c]=dep[u]+1, par[c]=u;
            dfs1(c,u);
            siz[u]+=siz[c];
            if (son[u]==-1||siz[son[u]]<siz[c]) son[u]=c;
        }
    }
    void dfs2(int u,int p,int tp){
        top[u]=tp;
        dfn[u]=++cnt;
        rk[cnt]=u;
        if (son[u]==-1) return;
        dfs2(son[u],u,tp);
        for (auto c:G[u]){
            if (c==p||c==son[u]) continue;
            dfs2(c,u,c);
        }
    }
    int lca(int u,int v){
        while (top[u]!=top[v]){
            if (dep[top[u]]>dep[top[v]]){
                u=par[top[u]];
            }
            else{
                v=par[top[v]];
            }
        }
        return dep[u]>dep[v]?v:u;
    }
    vector<pii> find_seg(int u,int v){
        vector<pii> ft,bk,res;
        ft.clear(), bk.clear(), res.clear();
//        cout<<top[u]<<" "<<top[v]<<endl;
        while (top[u]!=top[v]){
            if (dep[top[u]]>dep[top[v]]){
                ft.pb({u,top[u]});
                u=par[top[u]];
            }
            else{
                bk.pb({top[v],v});
                v=par[top[v]];
            }
        }
        ft.pb({u,v});
        for (int i=0;i<sz(ft);++i) res.pb(ft[i]);
        for (int i=sz(bk);i>0;--i) res.pb(bk[i-1]);
        return res;
    }
};

struct BIT{
    vi C; int n;
    BIT(int n):n(n){C.resize(n+7,0);}
    void update(int u,int w){
        for (;u<=n;u+=u&(-u)) C[u]+=w;
    }
    int query(int u){
        int res=0;
        for (;u>0;u-=u&(-u)) res+=C[u];
        return res;
    }
};

vi topoSort(const vector<vi>& gr) {
	vi indeg(sz(gr)), ret;
	for (auto& li : gr) for (int x : li) indeg[x]++;
	queue<int> q; // use priority queue for lexic. smallest ans.
	rep(i,sz(gr)) if (indeg[i] == 0) q.push(-i);
	while (!q.empty()) {
		int i = -q.front(); // top() for priority queue
		ret.push_back(i);
		q.pop();
		for (int x : gr[i])
			if (--indeg[x] == 0) q.push(-x);
	}
	return ret;
}

struct Eulerian{
  public:
    Eulerian(int n,int m):_n(n),_m(m){
        path.clear();
        _g.resize(n,vector<pii>(0));
        pt.resize(n,0);
        vis.resize(m,0);
        deg.resize(n,0);
    }
    void add(int x,int y,int id){
        _g[x].pb({y,id});
        pt[x]++;
        nxt=x;
        deg[y]++;
    }
    bool solve(){
        rep(i,_n) if (deg[i]&1) return false;
        dfs(nxt);
        if (sz(path)<_m) return 0;
        return true;
    }
    vi solve_path(){
        if (!solve()) path.clear();
        reverse(range(path));
        return path;
    }
  private:
    int _n,_m,nxt;
    vi path;
    vector<vector<pii>> _g;
    vi pt;
    vi deg;
    vector<bool> vis;
    int abs(int u){
        if (u<0) return ~u;
        return u;
    }
    void dfs(int u){
        while (pt[u]){
            while (pt[u]&&vis[abs(_g[u][pt[u]-1].S)]) pt[u]--;
            if (!pt[u]) break;
            int to=_g[u][pt[u]-1].F, id=_g[u][pt[u]-1].S;
            vis[abs(id)]=1;
            dfs(to), path.pb(id);
        }
    }
};

template<class T> struct FWT{
  public:
    vector<T> OR(vector<T> &a){
        return _OR(a,1);
    }
    vector<T> ROR(vector<T> &a){
        return _OR(a,-1);
    }
    vector<T> AND(vector<T> &a){
        return _AND(a,1);
    }
    vector<T> RAND(vector<T> &a){
        return _AND(a,-1);
    }
    vector<T> XOR(vector<T> &a){
        return _XOR(a,1);
    }
    vector<T> RXOR(vector<T> &a){
        return _XOR(a,-1);
    }
  private:
    vector<T> _OR(vector<T> &a,int mode=1){
        vector<T> b(a);
        for (int i=0;(1<<i)<sz(a);++i){
            for (int j=0;j<sz(a);++j){
                if (j>>i&1) b[j]+=b[j^(1<<i)]*mode;
            }
        }
        return b;
    }
    vector<T> _AND(vector<T> &a,int mode=1){
        vector<T> b(a);
        for (int i=0;(1<<i)<sz(a);++i){
            for (int j=0;j<sz(a);++j){
                if (j>>i&1) b[j^(1<<i)]+=b[j]*mode;
            }
        }
        return b;
    }
    vector<T> _XOR(vector<T> &a,int mode=1){
        vector<T> b(a);
        for (int i=0;(1<<i)<sz(a);++i){
            for (int j=0;j<sz(a);++j){
                if (j>>i&1){
                    b[j^(1<<i)]+=b[j];
                    b[j]=b[j^(1<<i)]-2*b[j];
                    if (mode<0) b[j]/=2, b[j^(1<<i)]/=2;
                }
            }
        }
        return b;
    }
};

/* atcoder mincost-maxflow */

template <class Cap, class Cost> struct mcf_graph {
  public:
    mcf_graph() {}
    mcf_graph(int n) : _n(n), g(n) {}

    int add_edge(int from, int to, Cap cap, Cost cost) {
        assert(0 <= from && from < _n);
        assert(0 <= to && to < _n);
        int m = (int)(pos.size());
        pos.push_back({from, (int)(g[from].size())});
        g[from].push_back(_edge{to, (int)(g[to].size()), cap, cost});
        g[to].push_back(_edge{from, (int)(g[from].size()) - 1, 0, -cost});
        return m;
    }

    struct edge {
        int from, to;
        Cap cap, flow;
        Cost cost;
    };

    edge get_edge(int i) {
        int m = (int)(pos.size());
        assert(0 <= i && i < m);
        auto _e = g[pos[i].first][pos[i].second];
        auto _re = g[_e.to][_e.rev];
        return edge{
            pos[i].first, _e.to, _e.cap + _re.cap, _re.cap, _e.cost,
        };
    }
    std::vector<edge> edges() {
        int m = (int)(pos.size());
        std::vector<edge> result(m);
        for (int i = 0; i < m; i++) {
            result[i] = get_edge(i);
        }
        return result;
    }

    std::pair<Cap, Cost> flow(int s, int t) {
        return flow(s, t, std::numeric_limits<Cap>::max());
    }
    std::pair<Cap, Cost> flow(int s, int t, Cap flow_limit) {
        return slope(s, t, flow_limit).back();
    }
    std::vector<std::pair<Cap, Cost>> slope(int s, int t) {
        return slope(s, t, std::numeric_limits<Cap>::max());
    }
    std::vector<std::pair<Cap, Cost>> slope(int s, int t, Cap flow_limit) {
        assert(0 <= s && s < _n);
        assert(0 <= t && t < _n);
        assert(s != t);
        // variants (C = maxcost):
        // -(n-1)C <= dual[s] <= dual[i] <= dual[t] = 0
        // reduced cost (= e.cost + dual[e.from] - dual[e.to]) >= 0 for all edge
        std::vector<Cost> dual(_n, 0), dist(_n);
        std::vector<int> pv(_n), pe(_n);
        std::vector<bool> vis(_n);
        auto dual_ref = [&]() {
            std::fill(dist.begin(), dist.end(),
                      std::numeric_limits<Cost>::max());
            std::fill(pv.begin(), pv.end(), -1);
            std::fill(pe.begin(), pe.end(), -1);
            std::fill(vis.begin(), vis.end(), false);
            struct Q {
                Cost key;
                int to;
                bool operator<(Q r) const { return key > r.key; }
            };
            std::priority_queue<Q> que;
            dist[s] = 0;
            que.push(Q{0, s});
            while (!que.empty()) {
                int v = que.top().to;
                que.pop();
                if (vis[v]) continue;
                vis[v] = true;
                if (v == t) break;
                // dist[v] = shortest(s, v) + dual[s] - dual[v]
                // dist[v] >= 0 (all reduced cost are positive)
                // dist[v] <= (n-1)C
                for (int i = 0; i < (int)(g[v].size()); i++) {
                    auto e = g[v][i];
                    if (vis[e.to] || !e.cap) continue;
                    // |-dual[e.to] + dual[v]| <= (n-1)C
                    // cost <= C - -(n-1)C + 0 = nC
                    Cost cost = e.cost - dual[e.to] + dual[v];
                    if (dist[e.to] - dist[v] > cost) {
                        dist[e.to] = dist[v] + cost;
                        pv[e.to] = v;
                        pe[e.to] = i;
                        que.push(Q{dist[e.to], e.to});
                    }
                }
            }
            if (!vis[t]) {
                return false;
            }

            for (int v = 0; v < _n; v++) {
                if (!vis[v]) continue;
                // dual[v] = dual[v] - dist[t] + dist[v]
                //         = dual[v] - (shortest(s, t) + dual[s] - dual[t]) + (shortest(s, v) + dual[s] - dual[v])
                //         = - shortest(s, t) + dual[t] + shortest(s, v)
                //         = shortest(s, v) - shortest(s, t) >= 0 - (n-1)C
                dual[v] -= dist[t] - dist[v];
            }
            return true;
        };
        Cap flow = 0;
        Cost cost = 0, prev_cost = -1;
        std::vector<std::pair<Cap, Cost>> result;
        result.push_back({flow, cost});
        while (flow < flow_limit) {
            if (!dual_ref()) break;
            Cap c = flow_limit - flow;
            for (int v = t; v != s; v = pv[v]) {
                c = std::min(c, g[pv[v]][pe[v]].cap);
            }
            for (int v = t; v != s; v = pv[v]) {
                auto& e = g[pv[v]][pe[v]];
                e.cap -= c;
                g[v][e.rev].cap += c;
            }
            Cost d = -dual[s];
            flow += c;
            cost += c * d;
            if (prev_cost == d) {
                result.pop_back();
            }
            result.push_back({flow, cost});
            prev_cost = cost;
        }
        return result;
    }

  private:
    int _n;

    struct _edge {
        int to, rev;
        Cap cap;
        Cost cost;
    };

    std::vector<std::pair<int, int>> pos;
    std::vector<std::vector<_edge>> g;
};

struct S{
    int act,inact,mn;
};

using F = int;

S e(){
    return {0,0,1000*1000+6};
}

S op(S l,S r){
    if (l.mn==r.mn) return {l.act+r.act,l.inact+r.inact,l.mn};
    if (l.mn<r.mn) return{l.act,l.inact,l.mn};
    else return {r.act,r.inact,r.mn};
}

F id(){
    return 0;
}

S mapping(F l,S r){
    return {r.act,r.inact,r.mn+l};
}

F composition(F l,F r){
    return l+r;
}

const int maxn=500007;
lazy_segtree<S,op,e,F,mapping,composition,id> seg(1e6+10);
int n,q;
int a[maxn];
signed main(){
    ios::sync_with_stdio(false);
    cin.tie(0), cout.tie(0);
    cin>>n>>q;
    a[0]=1e6+5;
    rep1(i,1e6) seg.set(i,{0,1,0});
    rep1(i,n){
        cin>>a[i];
        if (a[i]>a[i-1]) seg.apply(a[i-1]+1,a[i]+1,1);
        else seg.apply(a[i]+1,a[i-1]+1,1);
        auto f=seg.get(a[i]);
        swap(f.act,f.inact);
        seg.set(a[i],f);
    }
    seg.apply(1,a[n]+1,1);
    while (q--){
        int pos,x;
        cin>>pos>>x;
        int prev=a[pos];
        auto ret=seg.get(a[pos]);
        swap(ret.act,ret.inact);
        seg.set(a[pos],ret);
        ret=seg.get(x);
        swap(ret.act,ret.inact);
        seg.set(x,ret);
        a[pos]=x;
        auto update=[&](int l,int r,int w){
//            cout<<l<<" "<<r<<" "<<w<<endl;
            if (l>r) swap(l,r);
            seg.apply(l+1,r+1,w);
        };
        update(a[pos-1],prev,-1);
        update(a[pos-1],x,1);
        update(a[pos+1],prev,-1);
        update(a[pos+1],x,1);
        ret=seg.prod(1,1e6+1);
        if (ret.mn<=1){
            assert(ret.mn==1);
            cout<<ret.act<<" ";
        }
        else cout<<0<<" ";
    }
    return 0;
}


//#pragma GCC optimize("Ofast")
//#pragma GCC target("avx")
//#undef LOCAL

#include <algorithm>

#include <array>

#include <cassert>

#include <complex>

#include <cstdio>

#include <bitset>

#include <cstring>

#include <iostream>

#include <map>

#include <numeric>

#include <queue>

#include <set>

#include <string>

#include <unordered_map>

#include <unordered_set>

#include <vector>

using namespace std;

using uint = unsigned int;
using ll = long long;
using ull = unsigned long long;
constexpr ll TEN(int n) { return (n == 0) ? 1 : 10 * TEN(n - 1); }
template <class T> using V = vector<T>;
template <class T> using VV = V<V<T>>;
template <class T, class U>
ostream& operator<<(ostream& os, const pair<T, U>& p) {
    return os << "P(" << p.first << ", " << p.second << ")";
}

template <class T> ostream& operator<<(ostream& os, const V<T>& v) {
    os << "[";
    for (auto d : v) os << d << ", ";
    return os << "]";
}

struct Scanner {
    FILE* fp = nullptr;
    char line[(1 << 15) + 1];
    size_t st = 0, ed = 0;
    void reread() {
        memmove(line, line + st, ed - st);
        ed -= st;
        st = 0;
        ed += fread(line + ed, 1, (1 << 15) - ed, fp);
        line[ed] = '\0';
    }
    bool succ() {
        while (true) {
            if (st == ed) {
                reread();
                if (st == ed) return false;
            }
            while (st != ed && isspace(line[st])) st++;
            if (st != ed) break;
        }
        if (ed - st <= 50) reread();
        return true;
    }
    template <class T, enable_if_t<is_same<T, string>::value, int> = 0>
    bool read_single(T& ref) {
        if (!succ()) return false;
        while (true) {
            size_t sz = 0;
            while (st + sz < ed && !isspace(line[st + sz])) sz++;
            ref.append(line + st, sz);
            st += sz;
            if (!sz || st != ed) break;
            reread();
        }
        return true;
    }
    template <class T, enable_if_t<is_integral<T>::value, int> = 0>
    bool read_single(T& ref) {
        if (!succ()) return false;
        bool neg = false;
        if (line[st] == '-') {
            neg = true;
            st++;
        }
        ref = T(0);
        while (isdigit(line[st])) {
            ref = 10 * ref + (line[st++] - '0');
        }
        if (neg) ref = -ref;
        return true;
    }
    template <class T> bool read_single(V<T>& ref) {
        for (auto& d : ref) {
            if (!read_single(d)) return false;
        }
        return true;
    }
    void read() {}
    template <class H, class... T> void read(H& h, T&... t) {
        bool f = read_single(h);
        assert(f);
        read(t...);
    }
    Scanner(FILE* _fp) : fp(_fp) {}
};

struct Printer {
  public:
    template <bool F = false> void write() {}
    template <bool F = false, class H, class... T>
    void write(const H& h, const T&... t) {
        if (F) write_single(' ');
        write_single(h);
        write<true>(t...);
    }
    template <class... T> void writeln(const T&... t) {
        write(t...);
        write_single('\n');
    }

    Printer(FILE* _fp) : fp(_fp) {}
    ~Printer() { flush(); }

  private:
    static constexpr size_t SIZE = 1 << 15;
    FILE* fp;
    char line[SIZE], small[50];
    size_t pos = 0;
    void flush() {
        fwrite(line, 1, pos, fp);
        pos = 0;
    }
    void write_single(const char& val) {
        if (pos == SIZE) flush();
        line[pos++] = val;
    }
    template <class T, enable_if_t<is_integral<T>::value, int> = 0>
    void write_single(T val) {
        if (pos > (1 << 15) - 50) flush();
        if (val == 0) {
            write_single('0');
            return;
        }
        if (val < 0) {
            write_single('-');
            val = -val; // todo min
        }
        size_t len = 0;
        while (val) {
            small[len++] = char('0' + (val % 10));
            val /= 10;
        }
        reverse(small, small + len);
        memcpy(line + pos, small, len);
        pos += len;
    }
    void write_single(const string& s) {
        for (char c : s) write_single(c);
    }
    void write_single(const char* s) {
        size_t len = strlen(s);
        for (size_t i = 0; i < len; i++) write_single(s[i]);
    }
    template <class T> void write_single(const V<T>& val) {
        auto n = val.size();
        for (size_t i = 0; i < n; i++) {
            if (i) write_single(' ');
            write_single(val[i]);
        }
    }
};

Scanner sc = Scanner(stdin);
Printer pr = Printer(stdout);

const int INF = TEN(9);

struct Node {
    using NP = Node*;
    NP l = nullptr, r = nullptr;
    int sz = 0;

    int cnt = 1, mi, ma, lw, up, ls = 0, rs = 0;
    Node(const V<int>& fi, int off, int _sz) : sz(_sz) {
        if (sz == 1) {
            mi = ma = fi[off];
            lw = up = fi[off];
            return;
        }
        l = new Node(fi, off, sz / 2);
        r = new Node(fi, off + sz / 2, sz - sz / 2);
        update();
    }
    void set(int k, int a) {
        if (sz == 1) {
            mi = ma = a;
            lw = up = a;
            return;
        }
        if (k < sz / 2) l->set(k, a);
        else r->set(k - sz / 2, a);
        update();
    }

    using Q = pair<pair<int, int>, int>;
    Q query(int x) { // (hit range, strict low)
        // hit!
        if (lw <= x && x <= up) {
            return {{lw, up}, rs};
        }
        if (sz == 1) {
            if (x < ma) {
                return {{INF, -INF}, 0};
            } else {
                return {{INF, -INF}, 1};
            }
        }
        if (x < lw) {
            return r->query(x);
        } else {
            Q res = l->query(x);
            int uc = l->cnt - res.second;
            res.second = cnt - uc;
            return res;
        }
    }

    void update() {
        mi = min(l->mi, r->mi);
        ma = max(l->ma, r->ma);
        auto que = r->query(l->mi);
        lw = min(l->mi, que.first.first);
        rs = que.second;

        que = l->query(max(l->mi, r->ma));
        up = max(r->ma, que.first.second);

        ls = l->cnt - que.second;
        if (que.first.first != INF) ls--;

        assert(lw <= up);
        cnt = 1 + ls + rs;

    }

};

int main() {
    int n, q;
    sc.read(n, q);
    V<int> a(n);
    for (int i = 0; i < n; i++) sc.read(a[i]);

    auto tr = new Node(a, 0, n);
    for (int ph = 0; ph < q; ph++) {
        int p, x;
        sc.read(p, x); p--;
        tr->set(p, x);
        pr.writeln(tr->cnt);
    }
    return 0;
}


#include <bits/stdc++.h>
#include <ext/pb_ds/assoc_container.hpp>
#include <ext/pb_ds/trie_policy.hpp>
#include <ext/rope>

#pragma GCC optimize("Ofast")
#pragma GCC optimization("unroll-loops, no-stack-protector")
#pragma GCC target("avx,avx2,fma")

using namespace std;
using namespace __gnu_pbds;
using namespace __gnu_cxx;

mt19937 rng(chrono::steady_clock::now().time_since_epoch().count());

#define fi first
#define se second
#define pb push_back
#define eb emplace_back
#define mp make_pair
#define gcd __gcd
#define fastio ios_base::sync_with_stdio(0); cin.tie(0); cout.tie(0)
#define rep(i, n) for (int i=0; i<(n); i++)
#define rep1(i, n) for (int i=1; i<=(n); i++)
#define all(x) (x).begin(), (x).end()
#define rall(x) (x).rbegin(), (x).rend()
#define endl "\n"

typedef long long ll;
typedef unsigned long long ull;
typedef unsigned uint;
typedef long double ld;
typedef pair<int, int> pii;
typedef pair<ll, ll> pll;
typedef vector<int> vi;
typedef vector<vector<int>> vvi;
typedef vector<ll> vll;
typedef vector<vector<ll>> vvll;
typedef vector<bool> vb;
typedef vector<vector<bool>> vvb;
template<typename _def> using ordered_set=tree<_def, null_type, less<_def>, rb_tree_tag, tree_order_statistics_node_update>;
typedef trie<string, null_type, trie_string_access_traits<>, pat_trie_tag, trie_prefix_search_node_update> pref_trie;

struct Node {
    int mn=0, lz=0, cnt=0;
    Node() {}
    Node(int x): mn(x), lz(0), cnt(1) {}
    friend Node operator + (const Node& a, const Node& b) {
        Node c;
        if(a.mn<b.mn) c.mn=a.mn, c.cnt=a.cnt;
        else if(b.mn<a.mn) c.mn=b.mn, c.cnt=b.cnt;
        else c.mn=a.mn, c.cnt=a.cnt+b.cnt;
        return c;
    }
    void push(Node& l, Node& r) {
        if(!lz) return;
        l.mn+=lz; l.lz+=lz;
        r.mn+=lz; r.lz+=lz;
        lz=0;
    }
};

template<int N>
struct SegTree {
    Node t[4*N+4];
    void upd_cnt(int pos, int val, int v=1, int l=1, int r=N) {
        if(l==r) {
            t[v].cnt+=val;
            return;
        }
        else {
            t[v].push(t[v*2], t[v*2+1]);
            int m=(l+r)/2;
            if(pos<=m) upd_cnt(pos, val, v*2, l, m);
            else upd_cnt(pos, val, v*2+1, m+1, r);
            t[v]=t[v*2]+t[v*2+1];
        }
    }
    void upd(int ql, int qr, int val, int v=1, int l=1, int r=N) {
        if(ql>r||qr<l) return;
        if(ql<=l&&qr>=r) {
            t[v].mn+=val;
            t[v].lz+=val;
            return;
        }
        else {
            t[v].push(t[v*2], t[v*2+1]);
            int m=(l+r)/2;
            upd(ql, qr, val, v*2, l, m);
            upd(ql, qr, val, v*2+1, m+1, r);
            t[v]=t[v*2]+t[v*2+1];
        }
    }
    int get_top() {return t[1].cnt;}
};

constexpr int N=1e6+2;
int a[N];
SegTree<N> t;

int32_t main() {
    fastio;
    int n, q; cin>>n>>q;
    a[0]=N, a[n+1]=0; rep1(i, n) cin>>a[i];
    rep(i, n+1) {
        if(a[i]>a[i+1]) t.upd(a[i+1]+1, a[i], 1);
		if(i) t.upd_cnt(a[i], 1);
    }
    while(q--) {
        int x, v; cin>>x>>v;
        t.upd_cnt(a[x], -1);
        if(a[x]>a[x+1]) t.upd(a[x+1]+1, a[x], -1);
        if(a[x-1]>a[x]) t.upd(a[x]+1, a[x-1], -1);
        a[x]=v;
        t.upd_cnt(a[x], 1);
        if(a[x]>a[x+1]) t.upd(a[x+1]+1, a[x], 1);
        if(a[x-1]>a[x]) t.upd(a[x]+1, a[x-1], 1);
        cout<<t.get_top()<<endl;
    }
}


// Resubmission of the last compilation error submission.
// I think it'll get a run time error as well...
#ifndef LOCAL
#define NDEBUG
#endif
#include<array>
#include<cassert>
#include<algorithm>
#include<climits>
#include<cstdio>

#pragma GCC diagnostic push
#pragma GCC diagnostic ignored "-Wconversion"
namespace io{using namespace std;static const int buf_size=4096;static unsigned char buf[buf_size];static int buf_len=0,buf_pos=0;inline bool isEof(){if(buf_pos==buf_len){buf_pos=0,buf_len=fread(buf,1,buf_size,stdin);if(buf_pos==buf_len)return 1;}return 0;}inline int getChar(){return isEof()?-1:buf[buf_pos++];}inline int peekChar(){return isEof()?-1:buf[buf_pos];}inline bool seekEof(){int c;while((c=peekChar())!=-1&&c<=32)buf_pos++;return c==-1;}inline void skipBlanks(){while(!isEof()&&buf[buf_pos]<=32U)buf_pos++;}inline int readChar(){int c=getChar();while(c!=-1&&c<=32)c=getChar();return c;}inline int readUInt(){int c=readChar(),x=0;while('0'<=c&&c<='9')x=x*10+c-'0',c=getChar();return x;}template<class T=int>inline T readInt(){int s=1,c=readChar();T x=0;if(c=='-')s=-1,c=getChar();else if(c=='+')c=getChar();while('0'<=c&&c<='9')x=x*10+c-'0',c=getChar();return s==1?x:-x;}inline double readDouble(){int s=1,c=readChar();double x=0;if(c=='-')s=-1,c=getChar();while('0'<=c&&c<='9')x=x*10+c-'0',c=getChar();if(c=='.'){c=getChar();double coef=1;while('0'<=c&&c<='9')x+=(c-'0')*(coef*=1e-1),c=getChar();}return s==1?x:-x;}inline void readWord(char*s){int c=readChar();while(c>32)*s++=c,c=getChar();*s=0;}inline bool readLine(char*s){int c=getChar();while(c!='\n'&&c!=-1)*s++=c,c=getChar();*s=0;return c!=-1;}static int write_buf_pos=0;static char write_buf[buf_size];inline void writeChar(int x){if(write_buf_pos==buf_size)fwrite(write_buf,1,buf_size,stdout),write_buf_pos=0;write_buf[write_buf_pos++]=x;}inline void flush(){if(write_buf_pos){fwrite(write_buf,1,write_buf_pos,stdout),write_buf_pos=0;fflush(stdout);}}template<class T>inline void writeInt(T x,char end=0,int output_len=-1){if(x<0)writeChar('-'),x=-x;char s[24];int n=0;while(x||!n)s[n++]='0'+x%10,x/=10;while(n<output_len)s[n++]='0';while(n--)writeChar(s[n]);if(end)writeChar(end);}inline void writeWord(const char*s){while(*s)writeChar(*s++);}inline void writeDouble(double x,int output_len=0){if(x<0)writeChar('-'),x=-x;int t=(int)x;writeInt(t),x-=t;writeChar('.');for(int i=output_len-1;i>0;i--){x*=10;t=std::min(9,(int)x);writeChar('0'+t),x-=t;}x*=10;t=std::min(9,(int)(x+0.5));writeChar('0'+t);}static struct buffer_flusher_t{~buffer_flusher_t(){flush();}}buffer_flusher;};
#pragma GCC diagnostic pop

#include<vector>

int const BLOCKSIZE=1000;

struct block{
	struct interval{ // inclusive
		int l,r;
	};
	std::vector<interval> d;
	int min,max;

	template<class Iter>
	void recompute(Iter first,Iter last){
		assert(last-first<=BLOCKSIZE+1);
		assert(last-first>=2);

		std::array<int,BLOCKSIZE+1> minpre,maxsuf;
		d.reserve(last-first-1);
		d.clear();

		min=*first;
		for(int i=0;first+i!=last;++i)
			minpre[i]=min=std::min(min,first[i]);

		max=last[-1];
		for(auto i=last-first;i--;)
			maxsuf[i]=max=std::max(max,first[i]);

		for(auto i=last-first-1;i;--i){
			assert(minpre[i-1]!=maxsuf[i]);
			if(minpre[i-1]>maxsuf[i])
				d.push_back({maxsuf[i],minpre[i-1]});
		}

		assert(std::is_sorted(begin(d),end(d),[](interval x,interval y){
					return x.l<y.l;
					}));
	} // only O(n)

	int get(int minpre,int maxsuf)const{
		if(minpre<maxsuf)return 0;
		assert(minpre>maxsuf);
		auto const cond1=[](interval x,int y){return x.l<=y;};
		auto max_iter=cond1(d.back(),minpre) ? end(d) : std::lower_bound(begin(d),end(d),minpre,cond1);

		auto const cond2=[](interval x,int y){return x.r<y;};
		auto min_iter=cond2(d[0],maxsuf) ? begin(d) : std::lower_bound(begin(d),max_iter,maxsuf,cond2);

		return max_iter-min_iter;
		// number of segments that intersect [maxsuf..minpre]
	}
};

int main(){
	int n=io::readUInt();
	int nquery=io::readUInt();
	std::vector<int> a(n);
	std::generate(begin(a),end(a),io::readUInt);

	std::vector<block> blocks;
	for(int i=0;n-i*BLOCKSIZE>=2;++i){
		blocks.emplace_back();
		blocks[i].recompute(begin(a)+i*BLOCKSIZE,
				begin(a)+std::min((int)a.size(),i*BLOCKSIZE+BLOCKSIZE+1));
	}
	// NOTE one update may modify at most 2 block

	std::vector<int> maxsuf(blocks.size()+1);

	std::vector<int> minpre(blocks.size()+1); // exclusive

	auto const recompute_minmax=[&](){
		maxsuf.back()=INT_MIN;
		for(auto blocki=blocks.size();blocki--;)
			maxsuf[blocki]=std::max(maxsuf[blocki+1],blocks[blocki].max);

		minpre[0]=INT_MAX;
		for(auto blocki=1;blocki<=blocks.size();++blocki)
			minpre[blocki]=std::min(minpre[blocki-1],blocks[blocki-1].min);
	};
	recompute_minmax();

	int out=0;
	for(unsigned blocki=0;blocki<blocks.size();++blocki)
		out+=blocks[blocki].get(minpre[blocki],maxsuf[blocki+1]);

	while(nquery--){
		int pos=io::readUInt()-1;
		int x=io::readUInt();

		assert(x!=a[pos]);
		a[pos]=x;

		auto mincblock=pos==0 ? 0 : (pos-1)/BLOCKSIZE;
		auto maxcblock=pos/BLOCKSIZE;

		for(int blocki=mincblock;blocki<=maxcblock;++blocki)
			blocks[blocki].recompute(begin(a)+blocki*BLOCKSIZE,
					begin(a)+std::min((int)a.size(),blocki*BLOCKSIZE+BLOCKSIZE+1));

		auto const old_minpre=minpre;
		auto const old_maxsuf=maxsuf;

		recompute_minmax();

		out=0;
		for(unsigned blocki=0;blocki<blocks.size();++blocki){
			out+=blocks[blocki].get(minpre[blocki],maxsuf[blocki+1]);
		}
		io::writeInt(out+1 /* nblock = nsplit+1 */);
		io::writeChar('\n');
	}
}


// I was hinted at the square root decomposition by the large time limit... (is that cheating?)
#ifndef LOCAL
#define NDEBUG
#endif
#include<cassert>
#include<algorithm>
#include<climits>
#include<cstdio>

#pragma GCC diagnostic push
#pragma GCC diagnostic ignored "-Wconversion"
namespace io{using namespace std;static const int buf_size=4096;static unsigned char buf[buf_size];static int buf_len=0,buf_pos=0;inline bool isEof(){if(buf_pos==buf_len){buf_pos=0,buf_len=fread(buf,1,buf_size,stdin);if(buf_pos==buf_len)return 1;}return 0;}inline int getChar(){return isEof()?-1:buf[buf_pos++];}inline int peekChar(){return isEof()?-1:buf[buf_pos];}inline bool seekEof(){int c;while((c=peekChar())!=-1&&c<=32)buf_pos++;return c==-1;}inline void skipBlanks(){while(!isEof()&&buf[buf_pos]<=32U)buf_pos++;}inline int readChar(){int c=getChar();while(c!=-1&&c<=32)c=getChar();return c;}inline int readUInt(){int c=readChar(),x=0;while('0'<=c&&c<='9')x=x*10+c-'0',c=getChar();return x;}template<class T=int>inline T readInt(){int s=1,c=readChar();T x=0;if(c=='-')s=-1,c=getChar();else if(c=='+')c=getChar();while('0'<=c&&c<='9')x=x*10+c-'0',c=getChar();return s==1?x:-x;}inline double readDouble(){int s=1,c=readChar();double x=0;if(c=='-')s=-1,c=getChar();while('0'<=c&&c<='9')x=x*10+c-'0',c=getChar();if(c=='.'){c=getChar();double coef=1;while('0'<=c&&c<='9')x+=(c-'0')*(coef*=1e-1),c=getChar();}return s==1?x:-x;}inline void readWord(char*s){int c=readChar();while(c>32)*s++=c,c=getChar();*s=0;}inline bool readLine(char*s){int c=getChar();while(c!='\n'&&c!=-1)*s++=c,c=getChar();*s=0;return c!=-1;}static int write_buf_pos=0;static char write_buf[buf_size];inline void writeChar(int x){if(write_buf_pos==buf_size)fwrite(write_buf,1,buf_size,stdout),write_buf_pos=0;write_buf[write_buf_pos++]=x;}inline void flush(){if(write_buf_pos){fwrite(write_buf,1,write_buf_pos,stdout),write_buf_pos=0;fflush(stdout);}}template<class T>inline void writeInt(T x,char end=0,int output_len=-1){if(x<0)writeChar('-'),x=-x;char s[24];int n=0;while(x||!n)s[n++]='0'+x%10,x/=10;while(n<output_len)s[n++]='0';while(n--)writeChar(s[n]);if(end)writeChar(end);}inline void writeWord(const char*s){while(*s)writeChar(*s++);}inline void writeDouble(double x,int output_len=0){if(x<0)writeChar('-'),x=-x;int t=(int)x;writeInt(t),x-=t;writeChar('.');for(int i=output_len-1;i>0;i--){x*=10;t=std::min(9,(int)x);writeChar('0'+t),x-=t;}x*=10;t=std::min(9,(int)(x+0.5));writeChar('0'+t);}static struct buffer_flusher_t{~buffer_flusher_t(){flush();}}buffer_flusher;};
#pragma GCC diagnostic pop

#include<vector>

int const BLOCKSIZE=1000;

struct block{
	struct interval{ // inclusive
		int l,r;
	};
	std::vector<interval> d;
	int min,max;

	template<class Iter>
	void recompute(Iter first,Iter last){
		assert(last-first<=BLOCKSIZE+1);
		assert(last-first>=2);

		std::array<int,BLOCKSIZE+1> minpre,maxsuf;
		d.reserve(last-first-1);
		d.clear();

		min=*first;
		for(int i=0;first+i!=last;++i)
			minpre[i]=min=std::min(min,first[i]);

		max=last[-1];
		for(auto i=last-first;i--;)
			maxsuf[i]=max=std::max(max,first[i]);

		for(auto i=last-first-1;i;--i){
			assert(minpre[i-1]!=maxsuf[i]);
			if(minpre[i-1]>maxsuf[i])
				d.push_back({maxsuf[i],minpre[i-1]});
		}

		assert(std::is_sorted(begin(d),end(d),[](interval x,interval y){
					return x.l<y.l;
					}));
	} // only O(n)

	int get(int minpre,int maxsuf)const{
		if(minpre<maxsuf)return 0;
		assert(minpre>maxsuf);
		auto const cond1=[](interval x,int y){return x.l<=y;};
		auto max_iter=cond1(d.back(),minpre) ? end(d) : std::lower_bound(begin(d),end(d),minpre,cond1);

		auto const cond2=[](interval x,int y){return x.r<y;};
		auto min_iter=cond2(d[0],maxsuf) ? begin(d) : std::lower_bound(begin(d),max_iter,maxsuf,cond2);

		return max_iter-min_iter;
		// number of segments that intersect [maxsuf..minpre]
	}
};

int main(){
	int n=io::readUInt();
	int nquery=io::readUInt();
	std::vector<int> a(n);
	std::generate(begin(a),end(a),io::readUInt);

	std::vector<block> blocks;
	for(int i=0;n-i*BLOCKSIZE>=2;++i){
		blocks.emplace_back();
		blocks[i].recompute(begin(a)+i*BLOCKSIZE,
				begin(a)+std::min((int)a.size(),i*BLOCKSIZE+BLOCKSIZE+1));
	}
	// NOTE one update may modify at most 2 block

	std::vector<int> maxsuf(blocks.size()+1);

	std::vector<int> minpre(blocks.size()+1); // exclusive

	auto const recompute_minmax=[&](){
		maxsuf.back()=INT_MIN;
		for(auto blocki=blocks.size();blocki--;)
			maxsuf[blocki]=std::max(maxsuf[blocki+1],blocks[blocki].max);

		minpre[0]=INT_MAX;
		for(auto blocki=1;blocki<=blocks.size();++blocki)
			minpre[blocki]=std::min(minpre[blocki-1],blocks[blocki-1].min);
	};
	recompute_minmax();

	int out=0;
	for(unsigned blocki=0;blocki<blocks.size();++blocki)
		out+=blocks[blocki].get(minpre[blocki],maxsuf[blocki+1]);

	while(nquery--){
		int pos=io::readUInt()-1;
		int x=io::readUInt();

		assert(x!=a[pos]);
		a[pos]=x;

		auto mincblock=pos==0 ? 0 : (pos-1)/BLOCKSIZE;
		auto maxcblock=pos/BLOCKSIZE;

		for(int blocki=mincblock;blocki<=maxcblock;++blocki)
			blocks[blocki].recompute(begin(a)+blocki*BLOCKSIZE,
					begin(a)+std::min((int)a.size(),blocki*BLOCKSIZE+BLOCKSIZE+1));

		auto const old_minpre=minpre;
		auto const old_maxsuf=maxsuf;

		recompute_minmax();

		out=0;
		for(unsigned blocki=0;blocki<blocks.size();++blocki){
			out+=blocks[blocki].get(minpre[blocki],maxsuf[blocki+1]);
		}
		io::writeInt(out+1 /* nblock = nsplit+1 */);
		io::writeChar('\n');
	}
}