#include <bits/stdc++.h>
using namespace std;

// template {{{
#define pb push_back
#define eb emplace_back
#define mp make_pair
#define mt make_tuple
#define lb lower_bound
#define ub upper_bound
#define f first
#define s second
#define resz resize

#define sz(x) int((x).size())
#define all(x) (x).begin(), (x).end()

#define FOR(i, a, b) for (int i = (a); i < (b); i++)
#define F0R(i, a) for (int i = 0; i < (a); i++)
#define FORd(i, a, b) for (int i = (b)-1; i >= (a); i--)
#define F0Rd(i, a) for (int i = (a)-1; i >= 0; i--)
#define trav(a, x) for (auto& a : x)

#define sort_by(x, y) sort(all(x), [&](const auto& a, const auto& b) { return y; })

using ll = long long;
using vi = vector<int>;
using vvi = vector<vi>;
using vll = vector<ll>;
using vvll = vector<vll>;
using vb = vector<bool>;
using vd = vector<double>;
using vs = vector<string>;

using pii = pair<int, int>;
using pll = pair<ll, ll>;
using pdd = pair<double, double>;

using vpii = vector<pii>;
using vpll = vector<pll>;
using vpdd = vector<pdd>;

template<typename T> void ckmin(T& a, const T& b) { a = min(a, b); }
template<typename T> void ckmax(T& a, const T& b) { a = max(a, b); }

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

namespace __input {
    template<class T1, class T2> void re(pair<T1,T2>& p);
    template<class T> void re(vector<T>& a);
    template<class T, size_t SZ> void re(array<T,SZ>& a);

    template<class T> void re(T& x) { cin >> x; }
    void re(double& x) { string t; re(t); x = stod(t); }
    template<class Arg, class... Args> void re(Arg& first, Args&... rest) {
        re(first); re(rest...);
    }

    template<class T1, class T2> void re(pair<T1,T2>& p) { re(p.f,p.s); }
    template<class T> void re(vector<T>& a) { F0R(i,sz(a)) re(a[i]); }
    template<class T, size_t SZ> void re(array<T,SZ>& a) { F0R(i,SZ) re(a[i]); }
}
using namespace __input;

namespace __output {
    template<class T1, class T2> void pr(const pair<T1,T2>& x);
    template<class T, size_t SZ> void pr(const array<T,SZ>& x);
    template<class T> void pr(const vector<T>& x);
    template<class T> void pr(const set<T>& x);
    template<class T1, class T2> void pr(const map<T1,T2>& x);

    template<class T> void pr(const T& x) { cout << x; }
    template<class Arg, class... Args> void pr(const Arg& first, const Args&... rest) {
        pr(first); pr(rest...);
    }

    template<class T1, class T2> void pr(const pair<T1,T2>& x) {
        pr("{",x.f,", ",x.s,"}");
    }
    template<class T, bool pretty = true> void prContain(const T& x) {
        if (pretty) pr("{");
        bool fst = 1; for (const auto& a: x) pr(!fst?pretty?", ":" ":"",a), fst = 0;
        if (pretty) pr("}");
    }
    template<class T> void pc(const T& x) { prContain<T, false>(x); pr("\n"); }
    template<class T, size_t SZ> void pr(const array<T,SZ>& x) { prContain(x); }
    template<class T> void pr(const vector<T>& x) { prContain(x); }
    template<class T> void pr(const set<T>& x) { prContain(x); }
    template<class T1, class T2> void pr(const map<T1,T2>& x) { prContain(x); }

    void ps() { pr("\n"); }
    template<class Arg> void ps(const Arg& first) {
        pr(first); ps();
    }
    template<class Arg, class... Args> void ps(const Arg& first, const Args&... rest) {
        pr(first," "); ps(rest...);
    }
}
using namespace __output;

#define TRACE(x) x
#define __pn(x) pr(#x, " = ")
#define pd(...) __pn((__VA_ARGS__)), ps(__VA_ARGS__), cout << flush

namespace __algorithm {
    template<typename T> void dedup(vector<T>& v) {
        sort(all(v)); v.erase(unique(all(v)), v.end());
    }
    template<typename T> typename vector<T>::iterator find(const vector<T>& v, const T& x) {
        auto it = lower_bound(all(v), x); return it != v.end() && *it == x ? it : v.end();
    }
    template<typename T> size_t index(const vector<T>& v, const T& x) {
        auto it = find(v, x); assert(it != v.end() && *it == x); return it - v.begin();
    }

    template<typename T1, typename T2> typename vector<pair<T1, T2>>::iterator lower_bound(
            const vector<pair<T1, T2>>& v, const T1& x) {
        return lower_bound(all(v), x, [](pair<T1, T2> a, pair<T1, T2> b) { return a.f < b.f; });
    }
    template<typename T1, typename T2> typename vector<pair<T1, T2>>::iterator upper_bound(
            const vector<pair<T1, T2>>& v, const T1& x) {
        return upper_bound(all(v), x, [](pair<T1, T2> a, pair<T1, T2> b) { return a.f < b.f; });
    }
}
using namespace __algorithm;

struct monostate {
    friend istream& operator>>(istream& is, const __attribute__((unused))monostate& ms) { return is; }
    friend ostream& operator<<(ostream& os, const __attribute__((unused))monostate& ms) { return os; }
} ms;

template<typename W=monostate> struct wedge {
    int u, v, i; W w;
    wedge<W>(int _u=-1, int _v=-1, int _i=-1) : u(_u), v(_v), i(_i) {}
    int operator[](int loc) const { return u ^ v ^ loc; }
    friend void re(wedge& e) { re(e.u, e.v, e.w); --e.u, --e.v; }
    friend void pr(const wedge& e) { pr(e.u, "<-", e.w, "->", e.v); }
};

namespace __io {
    void setIn(string s) { freopen(s.c_str(),"r",stdin); }
    void setOut(string s) { freopen(s.c_str(),"w",stdout); }
    void setIO(string s = "") {
        ios_base::sync_with_stdio(0); cin.tie(0);
        if (sz(s)) { setIn(s+".in"), setOut(s+".out"); }
    }
}
using namespace __io;
// }}}

// modnum {{{
template<int MOD> struct modnum {
    int v;
    modnum() : v(0) {}
    modnum(ll _v) : v(_v % MOD) { if (v < 0) v += MOD; }
    explicit operator int() const { return v; }
    friend istream& operator >> (istream& i, modnum& n) { ll w; i >> w; n = modnum(w); return i; }
    friend ostream& operator << (ostream& o, const modnum& n) { return o << n.v; }

    friend bool operator == (const modnum& a, const modnum& b) { return a.v == b.v; }
    friend bool operator != (const modnum& a, const modnum& b) { return a.v != b.v; }

    modnum& operator += (const modnum& o) { v += o.v; if (v >= MOD) v -= MOD; return *this; }
    modnum& operator -= (const modnum& o) { v -= o.v; if (v < 0) v += MOD; return *this; }
    modnum& operator *= (const modnum& o) { v = int(ll(v) * ll(o.v) % MOD); return *this; }
    modnum operator - () { modnum res; if (v) res.v = MOD - v; return res; }
    friend modnum operator + (const modnum& a, const modnum& b) { return modnum(a) += b; }
    friend modnum operator - (const modnum& a, const modnum& b) { return modnum(a) -= b; }
    friend modnum operator * (const modnum& a, const modnum& b) { return modnum(a) *= b; }

    modnum pow(ll e) const {
        if (e < 0) return 1 / this->pow(-e);
        if (e == 0) return 1;
        if (e & 1) return *this * this->pow(e-1);
        return (*this * *this).pow(e/2);
    }

    modnum inv() const {
        int g = MOD, x = 0, y = 1;
        for (int r = v; r != 0; ) {
            int q = g / r;
            g %= r; swap(g, r);
            x -= q * y; swap(x, y);
        }

        assert(g == 1);
        assert(y == MOD || y == -MOD);
        return x < 0 ? x + MOD : x;
    }
    modnum& operator /= (const modnum& o) { return (*this) *= o.inv(); }
    friend modnum operator / (const modnum& a, const modnum& b) { return modnum(a) /= modnum(b); }

    static int totient() {
        int tot = MOD, tmp = MOD;
        for (int p = 2; p * p <= tmp; p++) if (tmp % p == 0) {
            tot = tot / p * (p - 1);
            while (tmp % p == 0) tmp /= p;
        }
        if (tmp > 1) tot = tot / tmp * (tmp - 1);
        return tot;
    }

    static int primitive_root() {
        if (MOD == 1) return 0;
        if (MOD == 2) return 1;

        int tot = totient(), tmp = tot;
        vi tot_pr;
        for (int p = 2; p * p <= tmp; p++) if (tot % p == 0) {
            tot_pr.push_back(p);
            while (tmp % p == 0) tmp /= p;
        }
        if (tmp > 1) tot_pr.push_back(tmp);

        for (int r = 2; r < MOD; r++) if (__gcd(r, MOD) == 1) {
            bool root = true;
            for (int p : tot_pr) root &= modnum(r).pow(tot / p) != 1;
            if (root) return r;
        }
        assert(false);
    }

    static modnum generator() { static modnum g = primitive_root(); return g; }
    static int discrete_log(modnum v) {
        static const int M = ceil(sqrt(MOD));
        static unordered_map<int, int> table;
        if (table.empty()) {
            modnum e = 1;
            for (int i = 0; i < M; i++) { table[e.v] = i; e *= generator(); }
        }
        static modnum f = generator().pow(totient() - M);

        for (int i = 0; i < M; i++) {
            if (table.count(v.v)) return table[v.v] + i * M;
            v *= f;
        }
        assert(false);
    }

    static modnum unity_root(int deg) {
        assert(totient() % deg == 0);
        return generator().pow(totient() / deg);
    }

    static modnum fact(int n) {
        static vector<modnum> fact = { 1 };
        for (assert(n >= 0); fact.size() <= n; )
            fact.push_back(fact.back() * fact.size());
        return fact[n];
    }

    static modnum finv(int n) {
        static vector<modnum> finv = { 1 };
        for (assert(n >= 0); finv.size() <= n; )
            finv.push_back(finv.back() / finv.size());
        return finv[n];
    }

    static modnum ncr(int n, int r) {
        assert(n >= 0);
        if (r < 0 || n < r) return 0;
        return fact(n) * finv(r) * finv(n - r);
    }
};
// }}}
using mn = modnum<int(998244353)>;
using vmn = vector<mn>;
using vvmn = vector<vmn>;

const int MAXV = 505;

bool did[MAXV][MAXV];
mn cache[MAXV][MAXV];

vi vals;
vi first, last;

mn solve(int i, int j) {
    if (i >= j) return 1;
    mn& ans = cache[i][j];
    if (did[i][j]) return ans;

    int k = min_element(vals.begin() + i, vals.begin() + j) - vals.begin();
    int left = first[vals[k]], right = last[vals[k]];
    if (left < i || right >= j) return ans = 0;

    mn lways = solve(i, left);
    FOR (sp, i, left) lways += solve(i, sp) * solve(sp, left);

    mn rways = solve(right+1, j);
    FOR (sp, right+1, j) rways += solve(right+1, sp) * solve(sp, j);

    mn ways = 1;
    int last = -1;
    FOR (m, left, right + 1) {
        if (vals[m] == vals[k]) {
            if (last != -1) ways *= solve(last + 1, m);
            last = m;
        }
    }

    did[i][j] = true;
    return ans = lways * ways * rways;
}

int main() {
    setIO();

    int N, M; re(N, M); vi strip(M); re(strip);
    trav (e, strip) --e;

    vvi locs(N);
    first.resz(N, INT_MAX), last.resz(N, -1);

    F0R (i, M) {
        locs[strip[i]].pb(i);
        ckmin(first[strip[i]], i);
        ckmax(last[strip[i]], i);
    }

    // first check if it's impossible
    set<int> alive;
    F0R (i, N) {
        auto it = alive.lower_bound(first[i]);
        if (it != alive.end() && *it < last[i]) {
            ps(0);
            return 0;
        }
        trav (e, locs[i]) alive.insert(e);
    }

    trav (e, strip) {
        if (vals.empty() || vals.back() != e)
            vals.pb(e);
    }

    fill(all(first), INT_MAX);
    fill(all(last), -1);
    F0R (i, sz(vals)) {
        ckmin(first[vals[i]], i);
        ckmax(last[vals[i]], i);
    }
    ps(solve(0, sz(vals)));

    return 0;
}


#include <bits/stdc++.h>
using namespace std;

// template {{{
#define pb push_back
#define eb emplace_back
#define mp make_pair
#define mt make_tuple
#define lb lower_bound
#define ub upper_bound
#define f first
#define s second
#define resz resize

#define sz(x) int((x).size())
#define all(x) (x).begin(), (x).end()

#define FOR(i, a, b) for (int i = (a); i < (b); i++)
#define F0R(i, a) for (int i = 0; i < (a); i++)
#define FORd(i, a, b) for (int i = (b)-1; i >= (a); i--)
#define F0Rd(i, a) for (int i = (a)-1; i >= 0; i--)
#define trav(a, x) for (auto& a : x)

#define sort_by(x, y) sort(all(x), [&](const auto& a, const auto& b) { return y; })

using ll = long long;
using vi = vector<int>;
using vvi = vector<vi>;
using vll = vector<ll>;
using vvll = vector<vll>;
using vb = vector<bool>;
using vd = vector<double>;
using vs = vector<string>;

using pii = pair<int, int>;
using pll = pair<ll, ll>;
using pdd = pair<double, double>;

using vpii = vector<pii>;
using vpll = vector<pll>;
using vpdd = vector<pdd>;

template<typename T> void ckmin(T& a, const T& b) { a = min(a, b); }
template<typename T> void ckmax(T& a, const T& b) { a = max(a, b); }

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

namespace __input {
    template<class T1, class T2> void re(pair<T1,T2>& p);
    template<class T> void re(vector<T>& a);
    template<class T, size_t SZ> void re(array<T,SZ>& a);

    template<class T> void re(T& x) { cin >> x; }
    void re(double& x) { string t; re(t); x = stod(t); }
    template<class Arg, class... Args> void re(Arg& first, Args&... rest) {
        re(first); re(rest...);
    }

    template<class T1, class T2> void re(pair<T1,T2>& p) { re(p.f,p.s); }
    template<class T> void re(vector<T>& a) { F0R(i,sz(a)) re(a[i]); }
    template<class T, size_t SZ> void re(array<T,SZ>& a) { F0R(i,SZ) re(a[i]); }
}
using namespace __input;

namespace __output {
    template<class T1, class T2> void pr(const pair<T1,T2>& x);
    template<class T, size_t SZ> void pr(const array<T,SZ>& x);
    template<class T> void pr(const vector<T>& x);
    template<class T> void pr(const set<T>& x);
    template<class T1, class T2> void pr(const map<T1,T2>& x);

    template<class T> void pr(const T& x) { cout << x; }
    template<class Arg, class... Args> void pr(const Arg& first, const Args&... rest) {
        pr(first); pr(rest...);
    }

    template<class T1, class T2> void pr(const pair<T1,T2>& x) {
        pr("{",x.f,", ",x.s,"}");
    }
    template<class T, bool pretty = true> void prContain(const T& x) {
        if (pretty) pr("{");
        bool fst = 1; for (const auto& a: x) pr(!fst?pretty?", ":" ":"",a), fst = 0;
        if (pretty) pr("}");
    }
    template<class T> void pc(const T& x) { prContain<T, false>(x); pr("\n"); }
    template<class T, size_t SZ> void pr(const array<T,SZ>& x) { prContain(x); }
    template<class T> void pr(const vector<T>& x) { prContain(x); }
    template<class T> void pr(const set<T>& x) { prContain(x); }
    template<class T1, class T2> void pr(const map<T1,T2>& x) { prContain(x); }

    void ps() { pr("\n"); }
    template<class Arg> void ps(const Arg& first) {
        pr(first); ps();
    }
    template<class Arg, class... Args> void ps(const Arg& first, const Args&... rest) {
        pr(first," "); ps(rest...);
    }
}
using namespace __output;

#define TRACE(x) x
#define __pn(x) pr(#x, " = ")
#define pd(...) __pn((__VA_ARGS__)), ps(__VA_ARGS__), cout << flush

namespace __algorithm {
    template<typename T> void dedup(vector<T>& v) {
        sort(all(v)); v.erase(unique(all(v)), v.end());
    }
    template<typename T> typename vector<T>::iterator find(const vector<T>& v, const T& x) {
        auto it = lower_bound(all(v), x); return it != v.end() && *it == x ? it : v.end();
    }
    template<typename T> size_t index(const vector<T>& v, const T& x) {
        auto it = find(v, x); assert(it != v.end() && *it == x); return it - v.begin();
    }

    template<typename T1, typename T2> typename vector<pair<T1, T2>>::iterator lower_bound(
            const vector<pair<T1, T2>>& v, const T1& x) {
        return lower_bound(all(v), x, [](pair<T1, T2> a, pair<T1, T2> b) { return a.f < b.f; });
    }
    template<typename T1, typename T2> typename vector<pair<T1, T2>>::iterator upper_bound(
            const vector<pair<T1, T2>>& v, const T1& x) {
        return upper_bound(all(v), x, [](pair<T1, T2> a, pair<T1, T2> b) { return a.f < b.f; });
    }
}
using namespace __algorithm;

struct monostate {
    friend istream& operator>>(istream& is, const __attribute__((unused))monostate& ms) { return is; }
    friend ostream& operator<<(ostream& os, const __attribute__((unused))monostate& ms) { return os; }
} ms;

template<typename W=monostate> struct wedge {
    int u, v, i; W w;
    wedge<W>(int _u=-1, int _v=-1, int _i=-1) : u(_u), v(_v), i(_i) {}
    int operator[](int loc) const { return u ^ v ^ loc; }
    friend void re(wedge& e) { re(e.u, e.v, e.w); --e.u, --e.v; }
    friend void pr(const wedge& e) { pr(e.u, "<-", e.w, "->", e.v); }
};

namespace __io {
    void setIn(string s) { freopen(s.c_str(),"r",stdin); }
    void setOut(string s) { freopen(s.c_str(),"w",stdout); }
    void setIO(string s = "") {
        ios_base::sync_with_stdio(0); cin.tie(0);
        if (sz(s)) { setIn(s+".in"), setOut(s+".out"); }
    }
}
using namespace __io;
// }}}

// modnum {{{
template<int MOD> struct modnum {
    int v;
    modnum() : v(0) {}
    modnum(ll _v) : v(_v % MOD) { if (v < 0) v += MOD; }
    explicit operator int() const { return v; }
    friend istream& operator >> (istream& i, modnum& n) { ll w; i >> w; n = modnum(w); return i; }
    friend ostream& operator << (ostream& o, const modnum& n) { return o << n.v; }

    friend bool operator == (const modnum& a, const modnum& b) { return a.v == b.v; }
    friend bool operator != (const modnum& a, const modnum& b) { return a.v != b.v; }

    modnum& operator += (const modnum& o) { v += o.v; if (v >= MOD) v -= MOD; return *this; }
    modnum& operator -= (const modnum& o) { v -= o.v; if (v < 0) v += MOD; return *this; }
    modnum& operator *= (const modnum& o) { v = int(ll(v) * ll(o.v) % MOD); return *this; }
    modnum operator - () { modnum res; if (v) res.v = MOD - v; return res; }
    friend modnum operator + (const modnum& a, const modnum& b) { return modnum(a) += b; }
    friend modnum operator - (const modnum& a, const modnum& b) { return modnum(a) -= b; }
    friend modnum operator * (const modnum& a, const modnum& b) { return modnum(a) *= b; }

    modnum pow(ll e) const {
        if (e < 0) return 1 / this->pow(-e);
        if (e == 0) return 1;
        if (e & 1) return *this * this->pow(e-1);
        return (*this * *this).pow(e/2);
    }

    modnum inv() const {
        int g = MOD, x = 0, y = 1;
        for (int r = v; r != 0; ) {
            int q = g / r;
            g %= r; swap(g, r);
            x -= q * y; swap(x, y);
        }

        assert(g == 1);
        assert(y == MOD || y == -MOD);
        return x < 0 ? x + MOD : x;
    }
    modnum& operator /= (const modnum& o) { return (*this) *= o.inv(); }
    friend modnum operator / (const modnum& a, const modnum& b) { return modnum(a) /= modnum(b); }

    static int totient() {
        int tot = MOD, tmp = MOD;
        for (int p = 2; p * p <= tmp; p++) if (tmp % p == 0) {
            tot = tot / p * (p - 1);
            while (tmp % p == 0) tmp /= p;
        }
        if (tmp > 1) tot = tot / tmp * (tmp - 1);
        return tot;
    }

    static int primitive_root() {
        if (MOD == 1) return 0;
        if (MOD == 2) return 1;

        int tot = totient(), tmp = tot;
        vi tot_pr;
        for (int p = 2; p * p <= tmp; p++) if (tot % p == 0) {
            tot_pr.push_back(p);
            while (tmp % p == 0) tmp /= p;
        }
        if (tmp > 1) tot_pr.push_back(tmp);

        for (int r = 2; r < MOD; r++) if (__gcd(r, MOD) == 1) {
            bool root = true;
            for (int p : tot_pr) root &= modnum(r).pow(tot / p) != 1;
            if (root) return r;
        }
        assert(false);
    }

    static modnum generator() { static modnum g = primitive_root(); return g; }
    static int discrete_log(modnum v) {
        static const int M = ceil(sqrt(MOD));
        static unordered_map<int, int> table;
        if (table.empty()) {
            modnum e = 1;
            for (int i = 0; i < M; i++) { table[e.v] = i; e *= generator(); }
        }
        static modnum f = generator().pow(totient() - M);

        for (int i = 0; i < M; i++) {
            if (table.count(v.v)) return table[v.v] + i * M;
            v *= f;
        }
        assert(false);
    }

    static modnum unity_root(int deg) {
        assert(totient() % deg == 0);
        return generator().pow(totient() / deg);
    }

    static modnum fact(int n) {
        static vector<modnum> fact = { 1 };
        for (assert(n >= 0); fact.size() <= n; )
            fact.push_back(fact.back() * fact.size());
        return fact[n];
    }

    static modnum finv(int n) {
        static vector<modnum> finv = { 1 };
        for (assert(n >= 0); finv.size() <= n; )
            finv.push_back(finv.back() / finv.size());
        return finv[n];
    }

    static modnum ncr(int n, int r) {
        assert(n >= 0);
        if (r < 0 || n < r) return 0;
        return fact(n) * finv(r) * finv(n - r);
    }
};
// }}}
using mn = modnum<int(998244353)>;
using vmn = vector<mn>;
using vvmn = vector<vmn>;

const int MAXV = 1005;

bool did[MAXV][MAXV];
mn cache[MAXV][MAXV];

vi vals;
vi first, last;

mn solve(int i, int j) {
    if (i >= j) return 1;
    mn& ans = cache[i][j];
    if (did[i][j]) return ans;
    did[i][j] = true;

    int k = min_element(vals.begin() + i, vals.begin() + j) - vals.begin();
    int left = first[vals[k]], right = last[vals[k]];
    if (left < i || right >= j) return ans = 0;

    mn lways = solve(i, left);
    FOR (sp, i, left) lways += solve(i, sp) * solve(sp, left);

    mn rways = solve(right+1, j);
    FOR (sp, right+1, j) rways += solve(right+1, sp) * solve(sp, j);

    mn ways = 1;
    int last = -1;
    FOR (m, left, right + 1) {
        if (vals[m] == vals[k]) {
            if (last != -1) ways *= solve(last + 1, m);
            last = m;
        }
    }

    return ans = lways * ways * rways;
}

int main() {
    setIO();

    int N, M; re(N, M); vi strip(M); re(strip);
    trav (e, strip) --e;

    vvi locs(N);
    first.resz(N, INT_MAX), last.resz(N, -1);

    F0R (i, M) {
        locs[strip[i]].pb(i);
        ckmin(first[strip[i]], i);
        ckmax(last[strip[i]], i);
    }

    // first check if it's impossible
    set<int> alive;
    F0R (i, N) {
        auto it = alive.lower_bound(first[i]);
        if (it != alive.end() && *it < last[i]) {
            ps(0);
            return 0;
        }
        trav (e, locs[i]) alive.insert(e);
    }

    trav (e, strip) {
        if (vals.empty() || vals.back() != e)
            vals.pb(e);
    }

    fill(all(first), INT_MAX);
    fill(all(last), -1);
    F0R (i, sz(vals)) {
        ckmin(first[vals[i]], i);
        ckmax(last[vals[i]], i);
    }
    ps(solve(0, sz(vals)));

    return 0;
}


#include <bits/stdc++.h>
using namespace std;
const int BASE = 998244353;

int n, m, c[1000100], newC[1010], minVal[1010][1010];
int firstId[555], lastId[555], isFirst[1010], isLast[1010], l[1000100], r[1000100];
int newL[1010], newR[1010];
vector<int> id[555];
long long f[1010][1010];

long long dp(int from, int to)
{
  if (from > to)
    return 1;

  if (!isFirst[from] || !isLast[to])
    return 0;

  if (from == to)
    return 1;

  if (f[from][to] >= 0)
    return f[from][to];

  int color = minVal[from][to];
  long long wayLeft = 0, wayRight = 0;

  for (int i = firstId[color]; i >= max(from, newL[firstId[color]]); i--)
    wayLeft = (wayLeft + dp(from, i - 1) * dp(i, firstId[color] - 1)) % BASE;
  for (int i = lastId[color]; i <= min(to, newR[lastId[color]]); i++)
    wayRight = (wayRight + dp(i + 1, to) * dp(lastId[color] + 1, i)) % BASE;

  f[from][to] = wayLeft * wayRight % BASE * dp(firstId[color] + 1, lastId[color] - 1) % BASE;
  return f[from][to];
}

void checkAns()
{
  for (int i = 1; i < n; i++)
    for (int j = i + 1; j <= n; j++)
    {
      int li = id[i][0], ri = id[i].back();
      int lj = id[j][0], rj = id[j].back();
      int isInside = (li < lj) && (rj < ri);
      int isOutside = (rj < li) || (ri < lj);
      if (!isInside && !isOutside)
      {
        cout << 0 << endl;
        exit(0);
      }
    }
}

void calcLR()
{
  for (int i = 0; i < m; i++)
  {
    l[i] = i;
    while (l[i] > 0 && c[i] <= c[l[i] - 1])
      l[i] = l[l[i] - 1];
  }
  for (int i = m - 1; i >= 0; i--)
  {
    r[i] = i;
    while (r[i] + 1 < m && c[i] <= c[r[i] + 1])
      r[i] = r[r[i] + 1];
  }
}

void compress()
{
  for (int i = 1; i <= n; i++)
  {
    firstId[i] = id[i][0];
    lastId[i] = id[i].back();
  }
  int newM = 1;
  isFirst[0] = 1;
  if (0 == lastId[c[0]])
    isLast[0] = 1;
  newC[0] = 0;
  for (int i = 1; i < m; i++)
    if (i == firstId[c[i]] || i == lastId[c[i]])
    {
      if (i == firstId[c[i]]) isFirst[newM] = 1;
      if (i == lastId[c[i]]) isLast[newM] = 1;
      newC[newM++] = i;
    }

  m = newM;

  for (int i = 0; i < m; i++)
  {
    if (isFirst[i])
      firstId[c[newC[i]]] = i;
    if (isLast[i])
      lastId[c[newC[i]]] = i;
  }

}

void init()
{
  for (int i = 0; i < m; i++)
  {
    int id = newC[i];
    newR[i] = upper_bound(newC, newC + m, r[id]) - newC;
    newR[i]--;
    newL[i] = lower_bound(newC, newC + m, l[id]) - newC;
  }

  for (int i = 0; i < m; i++)
  {
    minVal[i][i] = c[newC[i]];
    for (int j = i + 1; j < m; j++)
      minVal[i][j] = min(minVal[i][j - 1], c[newC[j]]);
  }
}

int main()
{
  ios_base::sync_with_stdio(0);
  cin.tie(0);

  cin >> n >> m;
  for (int i = 0; i < m; i++)
  {
    cin >> c[i];
    id[c[i]].push_back(i);
  }

  checkAns();
  calcLR();
  compress();
  init();

  memset(f, -1, sizeof f);
  cout << dp(0, m - 1) << endl;
}


#include <bits/stdc++.h>
using namespace std;
const int BASE = 998244353;

int n, m, c[1000100], newC[1010], minVal[1010][1010];
int firstId[555], lastId[555], isFirst[1010], isLast[1010], l[1000100], r[1000100];
int newL[1010], newR[1010];
vector<int> id[555];
long long f[1010][1010];

long long dp(int from, int to)
{
  if (from > to)
    return 1;

  if (!isFirst[from] || !isLast[to])
    return 0;

  if (from == to)
    return 1;

  if (f[from][to] >= 0)
    return f[from][to];

  int color = minVal[from][to];
  long long wayLeft = 0, wayRight = 0;

  for (int i = firstId[color]; i >= max(from, newL[firstId[color]]); i--)
    wayLeft = (wayLeft + dp(from, i - 1) * dp(i, firstId[color] - 1)) % BASE;
  for (int i = lastId[color]; i <= min(to, newR[lastId[color]]); i++)
    wayRight = (wayRight + dp(i + 1, to) * dp(lastId[color] + 1, i)) % BASE;

  f[from][to] = wayLeft * wayRight % BASE * dp(firstId[color] + 1, lastId[color] - 1) % BASE;
  return f[from][to];
}

void calcLR()
{
  for (int i = 0; i < m; i++)
  {
    l[i] = i;
    while (l[i] > 0 && c[i] <= c[l[i] - 1])
      l[i] = l[l[i] - 1];
  }
  for (int i = m - 1; i >= 0; i--)
  {
    r[i] = i;
    while (r[i] + 1 < m && c[i] <= c[r[i] + 1])
      r[i] = r[r[i] + 1];
  }

  for (int i = 1; i <= n; i++)
    if (r[id[i][0]] < id[i].back())
    {
      cout << 0 << endl;
      exit(0);
    }
}

void compress()
{
  for (int i = 1; i <= n; i++)
  {
    firstId[i] = id[i][0];
    lastId[i] = id[i].back();
  }
  int newM = 1;
  isFirst[0] = 1;
  if (0 == lastId[c[0]])
    isLast[0] = 1;
  newC[0] = 0;
  for (int i = 1; i < m; i++)
    if (i == firstId[c[i]] || i == lastId[c[i]])
    {
      if (i == firstId[c[i]]) isFirst[newM] = 1;
      if (i == lastId[c[i]]) isLast[newM] = 1;
      newC[newM++] = i;
    }

  m = newM;
  for (int i = 0; i < m; i++)
  {
    if (isFirst[i])
      firstId[c[newC[i]]] = i;
    if (isLast[i])
      lastId[c[newC[i]]] = i;
  }
}

void init()
{
  for (int i = 0; i < m; i++)
  {
    int id = newC[i];
    newR[i] = upper_bound(newC, newC + m, r[id]) - newC;
    newR[i]--;
    newL[i] = lower_bound(newC, newC + m, l[id]) - newC;
  }

  for (int i = 0; i < m; i++)
  {
    minVal[i][i] = c[newC[i]];
    for (int j = i + 1; j < m; j++)
      minVal[i][j] = min(minVal[i][j - 1], c[newC[j]]);
  }
}

int main()
{
  ios_base::sync_with_stdio(0);
  cin.tie(0);

  cin >> n >> m;
  for (int i = 0; i < m; i++)
  {
    cin >> c[i];
    id[c[i]].push_back(i);
  }

  calcLR();
  compress();
  init();

  memset(f, -1, sizeof f);
  cout << dp(0, m - 1) << endl;
}


#include <bits/stdc++.h>
using namespace std;
const int BASE = 998244353;

int n, m, c[1000100], newC[1010], minVal[1010][1010];
int firstId[555], lastId[555], isFirst[1010], isLast[1010], l[1000100], r[1000100];
int newL[1010], newR[1010];
vector<int> id[555];
long long f[1010][1010];

long long dp(int from, int to)
{
  if (from > to)
    return 1;

  if (!isFirst[from] || !isLast[to])
    return 0;

  if (from == to)
    return 1;

  if (f[from][to] >= 0)
    return f[from][to];

  int color = minVal[from][to];
  long long wayLeft = 0, wayRight = 0;

  for (int i = firstId[color]; i >= max(from, newL[firstId[color]]); i--)
    wayLeft = (wayLeft + dp(from, i - 1) * dp(i, firstId[color] - 1)) % BASE;
  for (int i = lastId[color]; i <= min(to, newR[lastId[color]]); i++)
    wayRight = (wayRight + dp(i + 1, to) * dp(lastId[color] + 1, i)) % BASE;

  f[from][to] = wayLeft * wayRight % BASE * dp(firstId[color] + 1, lastId[color] - 1) % BASE;
  return f[from][to];
}

void checkAns()
{
  for (int i = 1; i < n; i++)
    for (int j = i + 1; j <= n; j++)
    {
      int li = id[i][0], ri = id[i].back();
      int lj = id[j][0], rj = id[j].back();
      int isInside = (li < lj) && (rj < ri);
      int isOutside = (rj < li) || (ri < lj);
      if (!isInside && !isOutside)
      {
        cout << 0 << endl;
        exit(0);
      }
    }
}

void calcLR()
{
  for (int i = 0; i < m; i++)
  {
    l[i] = i;
    while (l[i] > 0 && c[i] <= c[l[i] - 1])
      l[i] = l[l[i] - 1];
  }
  for (int i = m - 1; i >= 0; i--)
  {
    r[i] = i;
    while (r[i] + 1 < m && c[i] <= c[r[i] + 1])
      r[i] = r[r[i] + 1];
  }
}

void compress()
{
  for (int i = 1; i <= n; i++)
  {
    firstId[i] = id[i][0];
    lastId[i] = id[i].back();
  }
  int newM = 1;
  isFirst[0] = 1;
  newC[0] = 0;
  for (int i = 1; i < m; i++)
    if (i == firstId[c[i]] || i == lastId[c[i]])
    {
      if (i == firstId[c[i]]) isFirst[newM] = 1;
      if (i == lastId[c[i]]) isLast[newM] = 1;
      newC[newM++] = i;
    }

  m = newM;

  for (int i = 0; i < m; i++)
  {
    if (isFirst[i])
      firstId[c[newC[i]]] = i;
    if (isLast[i])
      lastId[c[newC[i]]] = i;
  }
}

void init()
{
  for (int i = 0; i < m; i++)
  {
    int id = newC[i];
    newR[i] = upper_bound(newC, newC + m, r[id]) - newC;
    newR[i]--;
    newL[i] = lower_bound(newC, newC + m, l[id]) - newC;
  }

  for (int i = 0; i < m; i++)
  {
    minVal[i][i] = c[newC[i]];
    for (int j = i + 1; j < m; j++)
      minVal[i][j] = min(minVal[i][j - 1], c[newC[j]]);
  }
}

int main()
{
  ios_base::sync_with_stdio(0);
  cin.tie(0);

  cin >> n >> m;
  for (int i = 0; i < m; i++)
  {
    cin >> c[i];
    id[c[i]].push_back(i);
  }

  checkAns();
  calcLR();
  compress();
  init();

  memset(f, -1, sizeof f);
  cout << dp(0, m - 1) << endl;
}


#include<bits/stdc++.h>
using namespace std;
#define ll long long
#define mod 998244353
#define inf 0x3f3f3f3f
#define pb push_back
#define mp make_pair
#define P pair<int,int>
#define si set<int>
#define vi vector<int>
#define LL n<<1
#define RR n<<1|1
#define lson l,mid,LL
#define rson mid+1,r,RR
int dir[4][2]={1,0,-1,0,0,1,0,-1};
const int maxn=1005;
ll dp[maxn][maxn];
vi v[maxn];
int a[1000005],book[maxn],lo[maxn][maxn],ma[maxn],mi[maxn];
int main()
{
	int n,m;
	scanf("%d%d",&n,&m);
	for(int i=1;i<=m;i++)
		scanf("%d",&a[i]);
	int tot=0;
	for(int i=1;i<=m;i++)
	{
		if(i==1||a[i]!=a[i-1])
		a[++tot]=a[i];
	}
	m=tot;
	if(m>2*n)
	return 0*printf("0");
	for(int i=1;i<=m;i++)
	{
		ma[a[i]]=max(i,ma[a[i]]);
		if(!mi[a[i]])
		mi[a[i]]=i;
		v[a[i]].pb(i);
	}
	for(int i=1;i<=m;i++)
	{
		for(int j=1;j<=m;j++)
		{
			if(i==j)
			lo[i][j]=a[i];
			else
			lo[i][j]=min(lo[i][j-1],a[j]);
		}
	}
	for(int r=1;r<=m;r++)
	{
		for(int l=r;l>=1;l--)
		{
			int lll=mi[lo[l][r]],rr=ma[lo[l][r]];
			if(l==r)
			{
				dp[l][r]=!(lll<l||rr>r);
				dp[l][r-1]=1;
				dp[l+1][r]=1;
				continue;
			}
			if(lll<l||rr>r)
			{
				dp[l][r]=0;
				continue;
			}
			ll left,right,mid;
			left=right=0;
			mid=1;
			int now=lo[l][r];
			for(int k=l;k<=lll;k++)
				left=(left+dp[l][k-1]*dp[k][lll-1])%mod;
			for(int k=rr;k<=r;k++)
				right=(right+dp[k+1][r]*dp[rr+1][k])%mod;
			for(int k=1;k<v[now].size();k++)
				mid=mid*dp[v[now][k-1]+1][v[now][k]-1];
			dp[l][r]=1ll*left*right%mod*mid%mod;
		}
	}
	printf("%lld\n",dp[1][m]);
	return 0;
}


#include<bits/stdc++.h>
using namespace std;
#define ll long long
#define mod 998244353
#define inf 0x3f3f3f3f
#define pb push_back
#define mp make_pair
#define P pair<int,int>
#define si set<int>
#define vi vector<int>
#define LL n<<1
#define RR n<<1|1
#define lson l,mid,LL
#define rson mid+1,r,RR
int dir[4][2]={1,0,-1,0,0,1,0,-1};
const int maxn=1005;
ll dp[maxn][maxn];
vi v[maxn];
int a[maxn],book[maxn],lo[maxn][maxn],ma[maxn],mi[maxn];
int main()
{
	int n,m;
	scanf("%d%d",&n,&m);
	for(int i=1;i<=m;i++)
		scanf("%d",&a[i]);
	int tot=0;
	for(int i=1;i<=m;i++)
	{
		if(i==1||a[i]!=a[i-1])
		a[++tot]=a[i];
	}
	m=tot;
	if(m>2*n)
	return 0*printf("0");
	for(int i=1;i<=m;i++)
	{
		ma[a[i]]=max(i,ma[a[i]]);
		if(!mi[a[i]])
		mi[a[i]]=i;
		v[a[i]].pb(i);
	}
	for(int i=1;i<=m;i++)
	{
		for(int j=1;j<=m;j++)
		{
			if(i==j)
			lo[i][j]=a[i];
			else
			lo[i][j]=min(lo[i][j-1],a[j]);
		}
	}
	for(int r=1;r<=m;r++)
	{
		for(int l=r;l>=1;l--)
		{
			int lll=mi[lo[l][r]],rr=ma[lo[l][r]];
			if(l==r)
			{
				dp[l][r]=!(lll<l||rr>r);
				dp[l][r-1]=1;
				dp[l+1][r]=1;
				continue;
			}
			if(lll<l||rr>r)
			{
				dp[l][r]=0;
				continue;
			}
			ll left,right,mid;
			left=right=0;
			mid=1;
			int now=lo[l][r];
			for(int k=l;k<=lll;k++)
				left=(left+dp[l][k-1]*dp[k][lll-1])%mod;
			for(int k=rr;k<=r;k++)
				right=(right+dp[k+1][r]*dp[rr+1][k])%mod;
			for(int k=1;k<v[now].size();k++)
				mid=mid*dp[v[now][k-1]+1][v[now][k]-1];
			dp[l][r]=1ll*left*right%mod*mid%mod;
		}
	}
	printf("%lld\n",dp[1][m]);
	return 0;
}


#include<bits/stdc++.h>
using namespace std;
#define ll long long
#define mod 998244353
#define inf 0x3f3f3f3f
#define pb push_back
#define mp make_pair
#define P pair<int,int>
#define si set<int>
#define vi vector<int>
#define LL n<<1
#define RR n<<1|1
#define lson l,mid,LL
#define rson mid+1,r,RR
int dir[4][2]={1,0,-1,0,0,1,0,-1};
const int maxn=1005;
ll dp[maxn][maxn];
vi v[maxn];
int a[1000005],book[maxn],lo[maxn][maxn],ma[maxn],mi[maxn];
int main()
{
	int n,m;
	scanf("%d%d",&n,&m);
	for(int i=1;i<=m;i++)
		scanf("%d",&a[i]);
	int tot=0;
	for(int i=1;i<=m;i++)
	{
		if(i==1||a[i]!=a[i-1])
		a[++tot]=a[i];
	}
	m=tot;
	if(m>2*n)
	return 0*printf("0");
	for(int i=1;i<=m;i++)
	{
		ma[a[i]]=max(i,ma[a[i]]);
		if(!mi[a[i]])
		mi[a[i]]=i;
		v[a[i]].pb(i);
	}
	for(int i=1;i<=m;i++)
	{
		for(int j=1;j<=m;j++)
		{
			if(i==j)
			lo[i][j]=a[i];
			else
			lo[i][j]=min(lo[i][j-1],a[j]);
		}
	}
	for(int r=1;r<=m;r++)
	{
		for(int l=r;l>=1;l--)
		{
			int lll=mi[lo[l][r]],rr=ma[lo[l][r]];
			if(l==r)
			{
				dp[l][r]=!(lll<l||rr>r);
				dp[l][r-1]=1;
				dp[l+1][r]=1;
				continue;
			}
			if(lll<l||rr>r)
			{
				dp[l][r]=0;
				continue;
			}
			ll left,right,mid;
			left=right=0;
			mid=1;
			int now=lo[l][r];
			for(int k=l;k<=lll;k++)
				left=(left+dp[l][k-1]*dp[k][lll-1])%mod;
			for(int k=rr;k<=r;k++)
				right=(right+dp[k+1][r]*dp[rr+1][k])%mod;
			for(int k=1;k<v[now].size();k++)
				mid=mid*dp[v[now][k-1]+1][v[now][k]-1]%mod;
			dp[l][r]=1ll*left*right%mod*mid%mod;
		}
	}
	printf("%lld\n",dp[1][m]);
	return 0;
}


#include <bits/stdc++.h>

#define foreach(i,v) for(auto&& i: v)
#define all(x) (x).begin(), (x).end()

typedef std::vector< std::string > VS;
typedef std::vector<int> VI;
typedef long long ll;

template <class C> C& mini(C& a, C b) { if (b < a) a = b; return a; }
template <class C> C& maxi(C& a, C b) { if (a < b) a = b; return a; }

using namespace std;

template <typename T> void read(T& x) { x.read(); }
template <typename T> void read(vector<T>& v) { for (T& x: v) read(x); }
template <typename X, typename Y> void read(pair<X, Y>& p) { read(p.first); read(p.second); }
template <> void read(int& x) { scanf("%d", &x); }
template <> void read(unsigned int& x) { scanf("%u", &x); }
template <> void read(long long& x) { scanf("%lld", &x); }
template <> void read(unsigned long long& x) { scanf("%llu", &x); }
template <typename T> void readv(vector<T>& v) { int N; read(N); v.resize(N); read(v); }
template <typename T, typename ...Ts> void read(T& x, Ts&... args) { read(x); read(args...); }

struct Color {
    int first, last;
};

struct LL {
    int next, prev;
};

#define MOD 998244353

template <typename T>
void imfix(T& r) {
    if (r >= MOD)
        r -= MOD;
}

template <typename T>
T mfix(T r) {
    return r >= MOD ? r - MOD : r;
}

class SegMin {
public:
    SegMin(const VI& a) {
        const int N = a.size();
        B.push_back(a);
        for (int i = 1; (1 << i) <= N ; i++) {
            int l = 1 << i;
            B.push_back(VI());
            B.back().resize(N-l+1);
            for (int j = 0; j + l <= N; j++)
                B[i][j] = min(B[i-1][j], B[i-1][j+l/2]);
        }
    }

    int Min(int ll, int rr) {
        int len = rr - ll;
        int blen = 31 - __builtin_clz(len);
        len = 1 << blen;
        return min(B[blen][ll], B[blen][rr - len]);
    }

private:
    vector<VI> B;
};

VI A;
SegMin *segmin;
vector<Color> colors;
vector<LL> lls;
map<pair<int, int>, int> dp;
int dpc[512];

int solve(int l, int r);

int solve_dpc(int c) {
    int& rr = dpc[c];
    if (rr >= 0)
        return rr;
    ll ret = 1;
    int p = colors[c].first;

    while (lls[p].next != -1) {
        ret = (ret * solve(p+1, lls[p].next)) % MOD;
        p = lls[p].next;
    }

    return rr = (int)ret;
}

int _solve(int l, int r) {
    int c = segmin->Min(l, r);
    ll ret = solve_dpc(c);

    ll cnt;
    int p;

    cnt = 0;
    p = colors[c].first;
    assert(l <= p);
    while (1) {
        cnt = (cnt + (ll)solve(l, p) * solve(p, colors[c].first)) % MOD;
        if (p <= l)
            break;
        p = colors[A[p-1]].first;
    }
    ret = (ret * cnt) % MOD;

    cnt = 0;
    p = colors[c].last + 1;
    assert(p <= r);
    while (1) {
        cnt = (cnt + (ll)solve(colors[c].last+1, p) * solve(p, r)) % MOD;
        if (p >= r)
            break;
        p = colors[A[p]].last + 1;
    }
    ret = (ret * cnt) % MOD;

    return (int)ret;
}

int solve(int l, int r) {
    if (r - l <= 1)
        return 1;
    pair<int, int> key{l, r};
    auto it = dp.find(key);
    if (it != dp.end())
        return it->second;
    return dp[key] = _solve(l, r);
}

int main(int argc, const char* argv[]) {
    int N, M;
    memset(dpc, -1, sizeof(dpc));
    read(N, M);
    A.resize(M);
    read(A);
    colors.resize(N+1);
    lls.resize(M);
    foreach (c, colors)
        c.first = c.last = -1;

    for (int i = 0; i < M; i++) {
        Color& c = colors[A[i]];
        lls[i].prev = c.last;
        lls[i].next = -1;
        if (lls[i].prev >= 0)
            lls[lls[i].prev].next = i;
        if (c.first == -1)
            c.first = i;
        c.last = i;
    }

    for (int i = 1; i <= N; i++)
        for (int j = i+1; j <= N; j++) {
            if (colors[i].first < colors[j].first) {
               if (colors[j].first < colors[i].last && colors[i].last < colors[j].last) {
                   printf("0\n");
                   return 0;
               }
            } else {
                // colors[j].last < colors[i].last
                if (colors[i].first < colors[j].last) {
                    printf("0\n");
                    return 0;
                }
            }
        }
    segmin = new SegMin(A);
    printf("%d\n", solve(0, M));
    delete segmin;
    return 0;
}


#include <bits/stdc++.h>

#define foreach(i,v) for(auto&& i: v)
#define all(x) (x).begin(), (x).end()

typedef std::vector< std::string > VS;
typedef std::vector<int> VI;
typedef long long ll;

template <class C> C& mini(C& a, C b) { if (b < a) a = b; return a; }
template <class C> C& maxi(C& a, C b) { if (a < b) a = b; return a; }

using namespace std;

template <typename T> void read(T& x) { x.read(); }
template <typename T> void read(vector<T>& v) { for (T& x: v) read(x); }
template <typename X, typename Y> void read(pair<X, Y>& p) { read(p.first); read(p.second); }
template <> void read(int& x) { scanf("%d", &x); }
template <> void read(unsigned int& x) { scanf("%u", &x); }
template <> void read(long long& x) { scanf("%lld", &x); }
template <> void read(unsigned long long& x) { scanf("%llu", &x); }
template <typename T> void readv(vector<T>& v) { int N; read(N); v.resize(N); read(v); }
template <typename T, typename ...Ts> void read(T& x, Ts&... args) { read(x); read(args...); }

struct Color {
    int first, last;
};

struct LL {
    int next, prev;
};

#define MOD 998244353

template <typename T>
void imfix(T& r) {
    if (r >= MOD)
        r -= MOD;
}

template <typename T>
T mfix(T r) {
    return r >= MOD ? r - MOD : r;
}

class SegMin {
public:
    SegMin(const VI& a) {
        const int N = a.size();
        B.push_back(a);
        for (int i = 1; (1 << i) <= N ; i++) {
            int l = 1 << i;
            B.push_back(VI());
            B.back().resize(N-l+1);
            for (int j = 0; j + l <= N; j++)
                B[i][j] = min(B[i-1][j], B[i-1][j+l/2]);
        }
    }

    int Min(int ll, int rr) {
        int len = rr - ll;
        int blen = 31 - __builtin_clz(len);
        len = 1 << blen;
        return min(B[blen][ll], B[blen][rr - len]);
    }

private:
    vector<VI> B;
};

VI A;
SegMin *segmin;
vector<Color> colors;
vector<LL> lls;
map<pair<int, int>, int> dp;
int dpc[512];

int solve(int l, int r);

int solve_dpc(int c) {
    int& rr = dpc[c];
    if (rr >= 0)
        return rr;
    ll ret = 1;
    int p = colors[c].first;

    while (lls[p].next != -1) {
        ret = (ret * solve(p+1, lls[p].next)) % MOD;
        p = lls[p].next;
    }

    return rr = (int)ret;
}

int _solve(int l, int r) {
    int c = segmin->Min(l, r);
    ll ret = solve_dpc(c);

    ll cnt;
    int p;

    cnt = 0;
    p = colors[c].first;
    assert(l <= p);
    while (1) {
        cnt = (cnt + (ll)solve(l, p) * solve(p, colors[c].first)) % MOD;
        if (p <= l)
            break;
        p = colors[A[p-1]].first;
    }
    ret = (ret * cnt) % MOD;

    cnt = 0;
    p = colors[c].last + 1;
    assert(p <= r);
    while (1) {
        cnt = (cnt + (ll)solve(colors[c].last+1, p) * solve(p, r)) % MOD;
        if (p >= r)
            break;
        p = colors[A[p]].last + 1;
    }
    ret = (ret * cnt) % MOD;

    return (int)ret;
}

int solve(int l, int r) {
    if (r - l <= 1)
        return 1;
    pair<int, int> key{l, r};
    auto it = dp.find(key);
    if (it != dp.end())
        return it->second;
    return dp[key] = _solve(l, r);
}

int main(int argc, const char* argv[]) {
    int N, M;
    memset(dpc, -1, sizeof(dpc));
    read(N, M);
    A.resize(M);
    read(A);
    colors.resize(N+1);
    lls.resize(M);
    foreach (c, colors)
        c.first = c.last = -1;

    for (int i = 0; i < M; i++) {
        Color& c = colors[A[i]];
        lls[i].prev = c.last;
        lls[i].next = -1;
        if (lls[i].prev >= 0)
            lls[lls[i].prev].next = i;
        if (c.first == -1)
            c.first = i;
        c.last = i;
    }

    for (int i = 1; i <= N; i++)
        for (int j = i+1; j <= N; j++) {
            if (colors[i].first < colors[j].first) {
               if (colors[j].first < colors[i].last && colors[i].last < colors[j].last) {
                   printf("0\n");
                   return 0;
               }
            } else {
                // colors[j].last < colors[i].last
                if (colors[i].first < colors[j].last) {
                    printf("0\n");
                    return 0;
                }
            }
        }
    segmin = new SegMin(A);
    for (int i = 1; i <= N; i++)
        if (segmin->Min(colors[i].first, colors[i].last+1) < i) {
            printf("0\n");
            return 0;
        }
    printf("%d\n", solve(0, M));
    delete segmin;
    return 0;
}


#include <bits/stdc++.h>

#define foreach(i,v) for(auto&& i: v)
#define all(x) (x).begin(), (x).end()

typedef std::vector< std::string > VS;
typedef std::vector<int> VI;
typedef long long ll;

template <class C> C& mini(C& a, C b) { if (b < a) a = b; return a; }
template <class C> C& maxi(C& a, C b) { if (a < b) a = b; return a; }

using namespace std;

template <typename T> void read(T& x) { x.read(); }
template <typename T> void read(vector<T>& v) { for (T& x: v) read(x); }
template <typename X, typename Y> void read(pair<X, Y>& p) { read(p.first); read(p.second); }
template <> void read(int& x) { scanf("%d", &x); }
template <> void read(unsigned int& x) { scanf("%u", &x); }
template <> void read(long long& x) { scanf("%lld", &x); }
template <> void read(unsigned long long& x) { scanf("%llu", &x); }
template <typename T> void readv(vector<T>& v) { int N; read(N); v.resize(N); read(v); }
template <typename T, typename ...Ts> void read(T& x, Ts&... args) { read(x); read(args...); }

struct Color {
    int first, last;
};

struct LL {
    int next, prev;
};

#define MOD 998244353

template <typename T>
void imfix(T& r) {
    if (r >= MOD)
        r -= MOD;
}

template <typename T>
T mfix(T r) {
    return r >= MOD ? r - MOD : r;
}

class SegMin {
public:
    SegMin(int l, int r, const VI& a) :
        l(l), r(r)
    {
        if (l + 1 == r) {
            left = right = nullptr;
            v = a[l];
        } else {
            int m = (l + r) / 2;
            left = new SegMin(l, m, a);
            right = new SegMin(m, r, a);
            v = min(left->v, right->v);
        }
    }

    int Min(int ll, int rr) {
        if (ll >= r || rr <= l)
            return numeric_limits<int>::max();
        if (ll <= l && r <= rr)
            return v;
        return min(left->Min(ll, rr), right->Min(ll, rr));
    }

    ~SegMin() {
        delete left;
        delete right;
    }

private:
    int l, r, v;
    SegMin *left, *right;
};

VI A;
SegMin *segmin;
vector<Color> colors;
vector<LL> lls;
map<pair<int, int>, int> dp;

int solve(int l, int r);

int _solve(int l, int r) {
    int c = segmin->Min(l, r);
    ll ret = 1;
    int p = colors[c].first;

    while (lls[p].next != -1) {
        ret = (ret * solve(p+1, lls[p].next)) % MOD;
        p = lls[p].next;
    }

    ll cnt;

    cnt = 0;
    p = colors[c].first;
    assert(l <= p);
    while (1) {
        cnt = (cnt + (ll)solve(l, p) * solve(p, colors[c].first)) % MOD;
        if (p <= l)
            break;
        p = colors[A[p-1]].first;
    }
    ret = (ret * cnt) % MOD;

    cnt = 0;
    p = colors[c].last + 1;
    assert(p <= r);
    while (1) {
        cnt = (cnt + (ll)solve(colors[c].last+1, p) * solve(p, r)) % MOD;
        if (p >= r)
            break;
        p = colors[A[p]].last + 1;
    }
    ret = (ret * cnt) % MOD;

    return (int)ret;
}

int solve(int l, int r) {
    if (r - l <= 1)
        return 1;
    pair<int, int> key{l, r};
    auto it = dp.find(key);
    if (it != dp.end())
        return it->second;
    return dp[key] = _solve(l, r);
}

int main(int argc, const char* argv[]) {
    int N, M;
    read(N, M);
    A.resize(M);
    read(A);
    colors.resize(N+1);
    lls.resize(M);
    foreach (c, colors)
        c.first = c.last = -1;

    for (int i = 0; i < M; i++) {
        Color& c = colors[A[i]];
        lls[i].prev = c.last;
        lls[i].next = -1;
        if (lls[i].prev >= 0)
            lls[lls[i].prev].next = i;
        if (c.first == -1)
            c.first = i;
        c.last = i;
    }

    for (int i = 1; i <= N; i++)
        for (int j = i+1; j <= N; j++) {
            if (colors[i].first < colors[j].first) {
               if (colors[j].first < colors[i].last && colors[i].last < colors[j].last) {
                   printf("0\n");
                   return 0;
               }
            } else {
                // colors[j].last < colors[i].last
                if (colors[i].first < colors[j].last) {
                    printf("0\n");
                    return 0;
                }
            }
        }
    segmin = new SegMin(0, M, A);
    printf("%d\n", solve(0, M));
    delete segmin;
    return 0;
}


#include <bits/stdc++.h>

#define foreach(i,v) for(auto&& i: v)
#define all(x) (x).begin(), (x).end()

typedef std::vector< std::string > VS;
typedef std::vector<int> VI;
typedef long long ll;

template <class C> C& mini(C& a, C b) { if (b < a) a = b; return a; }
template <class C> C& maxi(C& a, C b) { if (a < b) a = b; return a; }

using namespace std;

template <typename T> void read(T& x) { x.read(); }
template <typename T> void read(vector<T>& v) { for (T& x: v) read(x); }
template <typename X, typename Y> void read(pair<X, Y>& p) { read(p.first); read(p.second); }
template <> void read(int& x) { scanf("%d", &x); }
template <> void read(unsigned int& x) { scanf("%u", &x); }
template <> void read(long long& x) { scanf("%lld", &x); }
template <> void read(unsigned long long& x) { scanf("%llu", &x); }
template <typename T> void readv(vector<T>& v) { int N; read(N); v.resize(N); read(v); }
template <typename T, typename ...Ts> void read(T& x, Ts&... args) { read(x); read(args...); }

struct Color {
    int first, last;
};

struct LL {
    int next, prev;
};

#define MOD 998244353

template <typename T>
void imfix(T& r) {
    if (r >= MOD)
        r -= MOD;
}

template <typename T>
T mfix(T r) {
    return r >= MOD ? r - MOD : r;
}

class SegMin {
public:
    SegMin(const VI& a) {
        const int N = a.size();
        B.push_back(a);
        for (int i = 1; (1 << i) <= N ; i++) {
            int l = 1 << i;
            B.push_back(VI());
            B.back().resize(N-l+1);
            for (int j = 0; j + l <= N; j++)
                B[i][j] = min(B[i-1][j], B[i-1][j+l/2]);
        }
    }

    int Min(int ll, int rr) {
        int len = rr - ll;
        int blen = 31 - __builtin_clz(len);
        len = 1 << blen;
        return min(B[blen][ll], B[blen][rr - len]);
    }

private:
    vector<VI> B;
};

VI A;
SegMin *segmin;
vector<Color> colors;
vector<LL> lls;
map<pair<int, int>, int> dp;

int solve(int l, int r);

int _solve(int l, int r) {
    int c = segmin->Min(l, r);
    ll ret = 1;
    int p = colors[c].first;

    while (lls[p].next != -1) {
        ret = (ret * solve(p+1, lls[p].next)) % MOD;
        p = lls[p].next;
    }

    ll cnt;

    cnt = 0;
    p = colors[c].first;
    assert(l <= p);
    while (1) {
        cnt = (cnt + (ll)solve(l, p) * solve(p, colors[c].first)) % MOD;
        if (p <= l)
            break;
        p = colors[A[p-1]].first;
    }
    ret = (ret * cnt) % MOD;

    cnt = 0;
    p = colors[c].last + 1;
    assert(p <= r);
    while (1) {
        cnt = (cnt + (ll)solve(colors[c].last+1, p) * solve(p, r)) % MOD;
        if (p >= r)
            break;
        p = colors[A[p]].last + 1;
    }
    ret = (ret * cnt) % MOD;

    return (int)ret;
}

int solve(int l, int r) {
    if (r - l <= 1)
        return 1;
    pair<int, int> key{l, r};
    auto it = dp.find(key);
    if (it != dp.end())
        return it->second;
    return dp[key] = _solve(l, r);
}

int main(int argc, const char* argv[]) {
    int N, M;
    read(N, M);
    A.resize(M);
    read(A);
    colors.resize(N+1);
    lls.resize(M);
    foreach (c, colors)
        c.first = c.last = -1;

    for (int i = 0; i < M; i++) {
        Color& c = colors[A[i]];
        lls[i].prev = c.last;
        lls[i].next = -1;
        if (lls[i].prev >= 0)
            lls[lls[i].prev].next = i;
        if (c.first == -1)
            c.first = i;
        c.last = i;
    }

    for (int i = 1; i <= N; i++)
        for (int j = i+1; j <= N; j++) {
            if (colors[i].first < colors[j].first) {
               if (colors[j].first < colors[i].last && colors[i].last < colors[j].last) {
                   printf("0\n");
                   return 0;
               }
            } else {
                // colors[j].last < colors[i].last
                if (colors[i].first < colors[j].last) {
                    printf("0\n");
                    return 0;
                }
            }
        }
    segmin = new SegMin(A);
    printf("%d\n", solve(0, M));
    delete segmin;
    return 0;
}


#include <bits/stdc++.h>

#define foreach(i,v) for(auto&& i: v)
#define all(x) (x).begin(), (x).end()

typedef std::vector< std::string > VS;
typedef std::vector<int> VI;
typedef long long ll;

template <class C> C& mini(C& a, C b) { if (b < a) a = b; return a; }
template <class C> C& maxi(C& a, C b) { if (a < b) a = b; return a; }

using namespace std;

template <typename T> void read(T& x) { x.read(); }
template <typename T> void read(vector<T>& v) { for (T& x: v) read(x); }
template <typename X, typename Y> void read(pair<X, Y>& p) { read(p.first); read(p.second); }
template <> void read(int& x) { scanf("%d", &x); }
template <> void read(unsigned int& x) { scanf("%u", &x); }
template <> void read(long long& x) { scanf("%lld", &x); }
template <> void read(unsigned long long& x) { scanf("%llu", &x); }
template <typename T> void readv(vector<T>& v) { int N; read(N); v.resize(N); read(v); }
template <typename T, typename ...Ts> void read(T& x, Ts&... args) { read(x); read(args...); }

struct Color {
    int first, last;
};

struct LL {
    int next, prev;
};

#define MOD 998244353

template <typename T>
void imfix(T& r) {
    if (r >= MOD)
        r -= MOD;
}

template <typename T>
T mfix(T r) {
    return r >= MOD ? r - MOD : r;
}

class SegMin {
public:
    SegMin(const VI& a) {
        const int N = a.size();
        B.push_back(a);
        for (int i = 1; (1 << i) <= N ; i++) {
            int l = 1 << i;
            B.push_back(VI());
            B.back().resize(N-l+1);
            for (int j = 0; j + l <= N; j++)
                B[i][j] = min(B[i-1][j], B[i-1][j+l/2]);
        }
    }

    int Min(int ll, int rr) {
        int len = rr - ll;
        int blen = 31 - __builtin_clz(len);
        len = 1 << blen;
        return min(B[blen][ll], B[blen][rr - len]);
    }

private:
    vector<VI> B;
};

VI A;
SegMin *segmin;
vector<Color> colors;
vector<LL> lls;
map<pair<int, int>, int> dp;
int dpc[512];

int solve(int l, int r);

int solve_dpc(int c) {
    int& rr = dpc[c];
    if (rr >= 0)
        return rr;
    ll ret = 1;
    int p = colors[c].first;

    while (lls[p].next != -1) {
        ret = (ret * solve(p+1, lls[p].next)) % MOD;
        p = lls[p].next;
    }

    return rr = (int)ret;
}

int _solve(int l, int r) {
    int c = segmin->Min(l, r);
    ll ret = solve_dpc(c);

    ll cnt;
    int p;

    cnt = 0;
    p = colors[c].first;
    assert(l <= p);
    while (1) {
        cnt = (cnt + (ll)solve(l, p) * solve(p, colors[c].first)) % MOD;
        if (p <= l)
            break;
        p = colors[A[p-1]].first;
    }
    ret = (ret * cnt) % MOD;

    cnt = 0;
    p = colors[c].last + 1;
    assert(p <= r);
    while (1) {
        cnt = (cnt + (ll)solve(colors[c].last+1, p) * solve(p, r)) % MOD;
        if (p >= r)
            break;
        p = colors[A[p]].last + 1;
    }
    ret = (ret * cnt) % MOD;

    return (int)ret;
}

int solve(int l, int r) {
    if (r - l <= 1)
        return 1;
    pair<int, int> key{l, r};
    auto it = dp.find(key);
    if (it != dp.end())
        return it->second;
    return dp[key] = _solve(l, r);
}

int main(int argc, const char* argv[]) {
    int N, M;
    memset(dpc, -1, sizeof(dpc));
    read(N, M);
    A.resize(M);
    read(A);
    colors.resize(N+1);
    lls.resize(M);
    foreach (c, colors)
        c.first = c.last = -1;

    for (int i = 0; i < M; i++) {
        Color& c = colors[A[i]];
        lls[i].prev = c.last;
        lls[i].next = -1;
        if (lls[i].prev >= 0)
            lls[lls[i].prev].next = i;
        if (c.first == -1)
            c.first = i;
        c.last = i;
    }

    for (int i = 1; i <= N; i++)
        for (int j = i+1; j <= N; j++) {
            if (colors[i].first < colors[j].first) {
               if (colors[j].first < colors[i].last && colors[i].last < colors[j].last) {
                   printf("0\n");
                   return 0;
               }
            } else {
                // colors[j].last < colors[i].last
                if (colors[i].first < colors[j].last) {
                    printf("0\n");
                    return 0;
                }
            }
        }
    segmin = new SegMin(A);
    for (int i = 1; i <= N; i++)
        if (segmin->Min(colors[i].first, colors[i].last) < i) {
            printf("0\n");
            return 0;
        }
    printf("%d\n", solve(0, M));
    delete segmin;
    return 0;
}


#include<bits/stdc++.h>
#define rep(i,a,b) for(register int i=a;i<=b;++i)
#define req(i,a,b) for(register int i=a;i>=b;--i)
#define rep_(i,a,b) for(register int i=a;i<b.size();++i)
#define rep1(i,a,b) for(register ll i=a;i<=b;++i)
#define rep2(i,a,b) for(i=a;i<=b;++i)
#define F(a) for(register int a=1;a<=n;++a)
#define M(a,b) memset(a,b,sizeof a)
#define DC int T;cin>>T;while(T--)
#define rd(a) a=read()
#define ll long long
#define R register
using namespace std;
const unsigned _mod=998244353;
const unsigned mod=1e9+7;
const ll infi=0x3f3f3f3f3f3f3f3fll;
const int inf=0x3f3f3f3f;
ll ksm(ll x,ll y){ll ret=1;while(y){if(y&1ll)ret=ret*x%mod;y>>=1ll;x=x*x%mod;}return ret;}
ll qpow(ll x,ll y,ll m){ll ret=1;while(y){if(y&1ll) ret=ret*x%m;y>>=1ll;x=x*x%m;}return ret;}
ll _gcd(ll x,ll y){return y?_gcd(y,x%y):x;}
ll read(){ll x=0,f=1;char ch=getchar();while(ch>'9'||ch<'0'){if(ch=='-')f=-1;ch=getchar();}while(ch>='0'&&ch<='9'){x=x*10+ch-'0';ch=getchar();}return x*f;}
#if 0
#pragma GCC optimize(3)
#pragma GCC target("avx")
#pragma GCC optimize("Ofast")
ll fac[200010],inv[200010];
fac[0]=inv[0]=1;
rep(i,1,200000) fac[i]=fac[i-1]*i%mod;
rep(i,1,200000) inv[i]=ksm(fac[i],mod-2);
ll C(ll n,ll m){if (m>n||m<0) return 0;return fac[n]*inv[m]%mod*inv[n-m]%mod;}
#define max(a,b) (a>b?a:b)
#define min(a,b) (a<b?a:b)
bool cmp(jyz x,jyz y){return x.a<y.a;}
int phi[1000010];
void phi_table(int n){phi[1]=1;rep(i,2,n) if (!phi[i]) for(R int j=i;j<=n;j+=i){if (!phi[j]) phi[j]=j;phi[j]=phi[j]*(i-1)/i;}}
This is a dividing line.
#endif
/*
    [[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]
    [[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]
    [[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]
*/
ll n,m,a[1000010],s[1010],t[1010],f[1010][1010];
int main()
{
	cin>>n>>m;
	rep(i,1,m) rd(a[i]);
	m=unique(a+1,a+m+1)-a-1;
	if (m>2*n-1) return puts("0"),0;
	F(i) s[i]=m+1;
	rep1(i,1,m) s[a[i]]=min(s[a[i]],i),t[a[i]]=max(t[a[i]],i);
	rep(i,0,m) f[i+1][i]=1;
	req(l,m,1) rep(r,l,m)
    {
		ll x=n+1,y=0;
		rep(k,l,r) x=min(x,a[k]);
		if (l>s[x]||r<t[x]) continue;
		rep(k,l,s[x]) y=(y+f[l][k-1]*f[k][s[x]-1])%mod;
		f[l][r]=y;y=0;
		rep(k,t[x],r) y=(y+f[k+1][r]*f[t[x]+1][k])%mod;
		f[l][r]=f[l][r]*y%mod;
        ll jyz=s[x];
		rep(k,s[x]+1,t[x]) if (a[k]==x) f[l][r]=f[l][r]*f[jyz+1][k-1]%mod,jyz=k;
	}
	cout<<f[1][m]<<'\n';
    return 0;
}


#include<bits/stdc++.h>
#define rep(i,a,b) for(register int i=a;i<=b;++i)
#define req(i,a,b) for(register int i=a;i>=b;--i)
#define rep_(i,a,b) for(register int i=a;i<b.size();++i)
#define rep1(i,a,b) for(register ll i=a;i<=b;++i)
#define rep2(i,a,b) for(i=a;i<=b;++i)
#define F(a) for(register int a=1;a<=n;++a)
#define M(a,b) memset(a,b,sizeof a)
#define DC int T;cin>>T;while(T--)
#define rd(a) a=read()
#define ll long long
#define R register
using namespace std;
const unsigned mod=998244353;
const unsigned _mod=1e9+7;
const ll infi=0x3f3f3f3f3f3f3f3fll;
const int inf=0x3f3f3f3f;
ll ksm(ll x,ll y){ll ret=1;while(y){if(y&1ll)ret=ret*x%mod;y>>=1ll;x=x*x%mod;}return ret;}
ll qpow(ll x,ll y,ll m){ll ret=1;while(y){if(y&1ll) ret=ret*x%m;y>>=1ll;x=x*x%m;}return ret;}
ll _gcd(ll x,ll y){return y?_gcd(y,x%y):x;}
ll read(){ll x=0,f=1;char ch=getchar();while(ch>'9'||ch<'0'){if(ch=='-')f=-1;ch=getchar();}while(ch>='0'&&ch<='9'){x=x*10+ch-'0';ch=getchar();}return x*f;}
#if 0
#pragma GCC optimize(3)
#pragma GCC target("avx")
#pragma GCC optimize("Ofast")
ll fac[200010],inv[200010];
fac[0]=inv[0]=1;
rep(i,1,200000) fac[i]=fac[i-1]*i%mod;
rep(i,1,200000) inv[i]=ksm(fac[i],mod-2);
ll C(ll n,ll m){if (m>n||m<0) return 0;return fac[n]*inv[m]%mod*inv[n-m]%mod;}
#define max(a,b) (a>b?a:b)
#define min(a,b) (a<b?a:b)
bool cmp(jyz x,jyz y){return x.a<y.a;}
int phi[1000010];
void phi_table(int n){phi[1]=1;rep(i,2,n) if (!phi[i]) for(R int j=i;j<=n;j+=i){if (!phi[j]) phi[j]=j;phi[j]=phi[j]*(i-1)/i;}}
This is a dividing line.
#endif
/*
    [[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]
    [[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]
    [[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]
*/
ll n,m,a[1000010],s[1010],t[1010],f[1010][1010];
int main()
{
	cin>>n>>m;
	rep(i,1,m) rd(a[i]);
	m=unique(a+1,a+m+1)-a-1;
	if (m>2*n-1) return puts("0"),0;
	F(i) s[i]=m+1;
	rep1(i,1,m) s[a[i]]=min(s[a[i]],i),t[a[i]]=max(t[a[i]],i);
	rep(i,0,m) f[i+1][i]=1;
	req(l,m,1) rep(r,l,m)
    {
		ll x=n+1,y=0;
		rep(k,l,r) x=min(x,a[k]);
		if (l>s[x]||r<t[x]) continue;
		rep(k,l,s[x]) y=(y+f[l][k-1]*f[k][s[x]-1])%mod;
		f[l][r]=y;y=0;
		rep(k,t[x],r) y=(y+f[k+1][r]*f[t[x]+1][k])%mod;
		f[l][r]=f[l][r]*y%mod;
        ll jyz=s[x];
		rep(k,s[x]+1,t[x]) if (a[k]==x) f[l][r]=f[l][r]*f[jyz+1][k-1]%mod,jyz=k;
	}
	cout<<f[1][m]<<'\n';
    return 0;
}


#include <cmath>
#include <vector>
#include <iostream>
#include <limits>
#include <iostream>
#include <vector>
#include <cassert>
#include <complex>
#include <cstdio>
#include <set>
#include <cstring>
#include <map>
#include <cmath>
#include <set>
#include <algorithm>
#include <queue>
#include <bitset>
#include <ctime>
#include <unordered_map>
#include <numeric>

using namespace std;
typedef long long Long;
typedef long double Double;
typedef vector<int> VI;
typedef vector<VI> VVI;
typedef pair<int,int> PII;
typedef pair<Long,Long> PLL;

int read(int &x) { return scanf("%d", &x); }
int read(int &x, int &y) { return scanf("%d%d", &x, &y); }
int read(int &x, int &y, int &z) { return scanf("%d%d%d", &x, &y, &z); }
int read(Long &x) { return scanf("%lld", &x); }
char buff[1000010];
int read(string &s) { int r = scanf("%s", buff); s = buff; return r; }

#define dlog2(n) (31-__builtin_clz(n))
template<class T>
struct SparseTable {
	int N, L;
	vector<vector<T>> table;
	SparseTable(const vector<T> &V):
			N(V.size()), L(dlog2(N)+1), table(L, vector<T>(N)){
		table[0] = V;
		for(int sz = 1; sz < L; ++sz){
			for (int i = 0; i < N; ++i) {
				if(i + (1<<sz) > N)break;
				table[sz][i] = min(table[sz-1][i], table[sz-1][i+(1<<(sz-1))]);
			}
		}
	}
	T get(int i, int j){
		int d = dlog2(j-i+1);
		return min(table[d][i], table[d][j-(1<<d)+1]);
	}
};

int MI[505][505];
#define MOD 998244353
int mul(int a, int b) {
	return 1LL*a*b%MOD;
}
int mul(int a, int b, int c) {
	return mul(mul(a, b), c);
}
int mem[502][502];
VI POS[502];
SparseTable<int> *ST;
int getMin(int i, int j) {
	return ST->get(i, j);
}
int N;
int dp(int l, int r) {
	if (l > r) return 1;
	if (mem[l][r] != -1) return mem[l][r];
	int id = getMin(l, r);
	int s = POS[id].front();
	int e = POS[id].back();
	int w = 1;
	{
		VI &P = POS[id];
		for (int i = 1; i < P.size(); ++i) {
			if (P[i-1] + 1 == P[i]) continue;
			w = mul(w, dp(P[i-1] + 1, P[i] - 1));
		}
	}
	int rw = 0;
	int lw = 0;
	for (int i = l; i <= s; ++i) {
		int t = mul(dp(l, i - 1), dp(i, s - 1));
		lw += t;
		if (lw >= MOD) lw -= MOD;
	}
	for (int j = e; j <= r; ++j) {
		int t = mul(dp(e+1, j), dp(j+1, r));
		rw += t;
		if (rw >= MOD) rw -= MOD;
	}
	return mem[l][r] = mul(lw, w, rw);
}
int VAL[1000010];
int dp2(int l, int r) {
	if (l >= r) return 1;
	int cl = VAL[l], cr = VAL[r];
	if (POS[cl].front() != l) return 0;
	if (POS[cr].back() != r) return 0;
	if (mem[cl][cr] != -1) return mem[cl][cr];
	int id = getMin(l, r);
	int s = POS[id].front();
	int e = POS[id].back();
	if (s < l || r < e) return 0;
	int w = 1;
	{
		VI &P = POS[id];
		for (int i = 1; i < P.size(); ++i) {
			if (P[i-1] + 1 == P[i]) continue;
			if (POS[VAL[P[i-1]+1]].front() != P[i-1]+1) return 0;
			if (POS[VAL[P[i]-1]].back()    != P[i]-1) return 0;
			w = mul(w, dp2(P[i-1]+1, P[i]-1));
		}
	}
	int rw = 0;
	int lw = 0;
	for (int i = 0; i < N; ++i) {
		int t = 0;
		PII range(POS[i].front(), POS[i].back());
		if (l <= range.first && range.first <= s) {
			t = mul(dp2(l, range.first-1), dp2(range.first, s-1));
		}
		lw += t;
		if (lw >= MOD) lw -= MOD;
	}
	for (int i = 0; i < N; ++i) {
		int t = 0;
		PII range(POS[i].front(), POS[i].back());
		if (e <= range.second && range.second <= r) {
			t = mul(dp2(e+1, range.second), dp2(range.second+1, r));
		}
		rw += t;
		if (rw >= MOD) rw -= MOD;
	}
	return mem[l][r] = mul(lw, w, rw);
}

int main() {

	int M;
	read(N, M);
	VI V(M);
	VI IV(M);
	memset(mem, -1, sizeof(mem));
	for (int i = 0; i < M; ++i) {
		read(V[i]); V[i]--;
		VAL[i] = V[i];
		POS[V[i]].push_back(i);
	}
	set<int> ALLP; ALLP.insert(-1); ALLP.insert(M);
	ST = new SparseTable<int>(V);
	cout << dp2(0, M-1) << endl;

}


#include <cmath>
#include <vector>
#include <iostream>
#include <limits>
#include <iostream>
#include <vector>
#include <cassert>
#include <complex>
#include <cstdio>
#include <set>
#include <cstring>
#include <map>
#include <cmath>
#include <set>
#include <algorithm>
#include <queue>
#include <bitset>
#include <ctime>
#include <unordered_map>
#include <numeric>

using namespace std;
typedef long long Long;
typedef long double Double;
typedef vector<int> VI;
typedef vector<VI> VVI;
typedef pair<int,int> PII;
typedef pair<Long,Long> PLL;

int read(int &x) { return scanf("%d", &x); }
int read(int &x, int &y) { return scanf("%d%d", &x, &y); }
int read(int &x, int &y, int &z) { return scanf("%d%d%d", &x, &y, &z); }
int read(Long &x) { return scanf("%lld", &x); }
char buff[1000010];
int read(string &s) { int r = scanf("%s", buff); s = buff; return r; }

#define dlog2(n) (31-__builtin_clz(n))
template<class T>
struct SparseTable {
	int N, L;
	vector<vector<T>> table;
	SparseTable(const vector<T> &V):
			N(V.size()), L(dlog2(N)+1), table(L, vector<T>(N)){
		table[0] = V;
		for(int sz = 1; sz < L; ++sz){
			for (int i = 0; i < N; ++i) {
				if(i + (1<<sz) > N)break;
				table[sz][i] = min(table[sz-1][i], table[sz-1][i+(1<<(sz-1))]);
			}
		}
	}
	T get(int i, int j){
		int d = dlog2(j-i+1);
		return min(table[d][i], table[d][j-(1<<d)+1]);
	}
};

int MI[505][505];
#define MOD 998244353
int mul(int a, int b) {
	return 1LL*a*b%MOD;
}
int mul(int a, int b, int c) {
	return mul(mul(a, b), c);
}
int mem[502][502];
VI POS[502];
SparseTable<int> *ST;
int getMin(int i, int j) {
	return ST->get(i, j);
}
int N;
int dp(int l, int r) {
	if (l > r) return 1;
	if (mem[l][r] != -1) return mem[l][r];
	int id = getMin(l, r);
	int s = POS[id].front();
	int e = POS[id].back();
	int w = 1;
	{
		VI &P = POS[id];
		for (int i = 1; i < P.size(); ++i) {
			if (P[i-1] + 1 == P[i]) continue;
			w = mul(w, dp(P[i-1] + 1, P[i] - 1));
		}
	}
	int rw = 0;
	int lw = 0;
	for (int i = l; i <= s; ++i) {
		int t = mul(dp(l, i - 1), dp(i, s - 1));
		lw += t;
		if (lw >= MOD) lw -= MOD;
	}
	for (int j = e; j <= r; ++j) {
		int t = mul(dp(e+1, j), dp(j+1, r));
		rw += t;
		if (rw >= MOD) rw -= MOD;
	}
	cout << l << " " << r << " -> " << mul(lw, w, rw) << endl;
	return mem[l][r] = mul(lw, w, rw);
}
int VAL[1000010];
int dp2(int l, int r) {
	if (l > r) return 1;
	int cl = VAL[l], cr = VAL[r];
	if (POS[cl].front() != l) return 0;
	if (POS[cr].back() != r) return 0;
	if (mem[cl][cr] != -1) return mem[cl][cr];
	int id = getMin(l, r);
	int s = POS[id].front();
	int e = POS[id].back();
	if (s < l || r < e) return 0;
	int w = 1;
	{
		VI &P = POS[id];
		for (int i = 1; i < P.size(); ++i) {
			if (P[i-1] + 1 == P[i]) continue;
			if (POS[VAL[P[i-1]+1]].front() != P[i-1]+1) return 0;
			if (POS[VAL[P[i]-1]].back()    != P[i]-1) return 0;
			w = mul(w, dp2(P[i-1]+1, P[i]-1));
		}
	}
	int rw = 0;
	int lw = 0;
	for (int i = 0; i < N; ++i) {
		int t = 0;
		PII range(POS[i].front(), POS[i].back());
		if (l <= range.first && range.first <= s) {
			t = mul(dp2(l, range.first-1), dp2(range.first, s-1));
		}
		lw += t;
		if (lw >= MOD) lw -= MOD;
	}
	for (int i = 0; i < N; ++i) {
		int t = 0;
		PII range(POS[i].front(), POS[i].back());
		if (e <= range.second && range.second <= r) {
			t = mul(dp2(e+1, range.second), dp2(range.second+1, r));
		}
		rw += t;
		if (rw >= MOD) rw -= MOD;
	}
	return mem[cl][cr] = mul(lw, w, rw);
}

int main() {

	int M;
	read(N, M);
	VI V(M);
	VI IV(M);
	for (int i = 0; i < M; ++i) {
		read(V[i]); V[i]--;
		VAL[i] = V[i];
		POS[V[i]].push_back(i);
	}
	set<int> ALLP; ALLP.insert(-1); ALLP.insert(M);
	ST = new SparseTable<int>(V);
	memset(mem, -1, sizeof(mem));
	cout << dp2(0, M-1) << endl;

}

/*
3 -> 2 -> 1
3 -> 1 -> 1
2 -> 1 -> 1
1 -> 2 -> 1
1 -> 1 -> 1

*/


#include <cmath>
#include <vector>
#include <iostream>
#include <limits>
#include <iostream>
#include <vector>
#include <cassert>
#include <complex>
#include <cstdio>
#include <set>
#include <cstring>
#include <map>
#include <cmath>
#include <set>
#include <algorithm>
#include <queue>
#include <bitset>
#include <ctime>
#include <unordered_map>
#include <numeric>

using namespace std;
typedef long long Long;
typedef long double Double;
typedef vector<int> VI;
typedef vector<VI> VVI;
typedef pair<int,int> PII;
typedef pair<Long,Long> PLL;

int read(int &x) { return scanf("%d", &x); }
int read(int &x, int &y) { return scanf("%d%d", &x, &y); }
int read(int &x, int &y, int &z) { return scanf("%d%d%d", &x, &y, &z); }
int read(Long &x) { return scanf("%lld", &x); }
char buff[1000010];
int read(string &s) { int r = scanf("%s", buff); s = buff; return r; }

#define dlog2(n) (31-__builtin_clz(n))
template<class T>
struct SparseTable {
	int N, L;
	vector<vector<T>> table;
	SparseTable(const vector<T> &V):
			N(V.size()), L(dlog2(N)+1), table(L, vector<T>(N)){
		table[0] = V;
		for(int sz = 1; sz < L; ++sz){
			for (int i = 0; i < N; ++i) {
				if(i + (1<<sz) > N)break;
				table[sz][i] = min(table[sz-1][i], table[sz-1][i+(1<<(sz-1))]);
			}
		}
	}
	T get(int i, int j){
		int d = dlog2(j-i+1);
		return min(table[d][i], table[d][j-(1<<d)+1]);
	}
};

int MI[505][505];
#define MOD 998244353
int mul(int a, int b) {
	return 1LL*a*b%MOD;
}
int mul(int a, int b, int c) {
	return mul(mul(a, b), c);
}
int mem[502][502];
VI POS[502];
SparseTable<int> *ST;
int getMin(int i, int j) {
	return ST->get(i, j);
}
int N;
int dp(int l, int r) {
	if (l > r) return 1;
	if (mem[l][r] != -1) return mem[l][r];
	int id = getMin(l, r);
	int s = POS[id].front();
	int e = POS[id].back();
	int w = 1;
	{
		VI &P = POS[id];
		for (int i = 1; i < P.size(); ++i) {
			if (P[i-1] + 1 == P[i]) continue;
			w = mul(w, dp(P[i-1] + 1, P[i] - 1));
		}
	}
	int rw = 0;
	int lw = 0;
	for (int i = l; i <= s; ++i) {
		int t = mul(dp(l, i - 1), dp(i, s - 1));
		lw += t;
		if (lw >= MOD) lw -= MOD;
	}
	for (int j = e; j <= r; ++j) {
		int t = mul(dp(e+1, j), dp(j+1, r));
		rw += t;
		if (rw >= MOD) rw -= MOD;
	}
	cout << l << " " << r << " -> " << mul(lw, w, rw) << endl;
	return mem[l][r] = mul(lw, w, rw);
}
int VAL[1000010];
int dp2(int l, int r) {
	if (l > r) return 1;
	int cl = VAL[l], cr = VAL[r];
	if (POS[cl].front() != l) return 0;
	if (POS[cr].back() != r) return 0;
	if (mem[cl][cr] != -1) return mem[cl][cr];
	int id = getMin(l, r);
	int s = POS[id].front();
	int e = POS[id].back();
	if (s < l || r < e) return 0;
	int w = 1;
	{
		VI &P = POS[id];
		for (int i = 1; i < P.size(); ++i) {
			if (P[i-1] + 1 == P[i]) continue;
			if (POS[VAL[P[i-1]+1]].front() != P[i-1]+1) return 0;
			if (POS[VAL[P[i]-1]].back()    != P[i]-1) return 0;
			w = mul(w, dp2(P[i-1]+1, P[i]-1));
		}
	}
	int rw = 0;
	int lw = 0;
	for (int i = 0; i < N; ++i) {
		int t = 0;
		PII range(POS[i].front(), POS[i].back());
		if (l <= range.first && range.first <= s) {
			t = mul(dp2(l, range.first-1), dp2(range.first, s-1));
		}
		lw += t;
		if (lw >= MOD) lw -= MOD;
	}
	for (int i = 0; i < N; ++i) {
		int t = 0;
		PII range(POS[i].front(), POS[i].back());
		if (e <= range.second && range.second <= r) {
			t = mul(dp2(e+1, range.second), dp2(range.second+1, r));
		}
		rw += t;
		if (rw >= MOD) rw -= MOD;
	}
	return mem[cl][cr] = mul(lw, w, rw);
}

int main() {

	int M;
	read(N, M);
	VI V(M);
	VI IV(M);
	memset(mem, -1, sizeof(mem));
	for (int i = 0; i < M; ++i) {
		read(V[i]); V[i]--;
		VAL[i] = V[i];
		POS[V[i]].push_back(i);
	}
	set<int> ALLP; ALLP.insert(-1); ALLP.insert(M);
	ST = new SparseTable<int>(V);
	cout << dp2(0, 6) << endl;

}

/*
3 -> 2 -> 1
3 -> 1 -> 1
2 -> 1 -> 1
1 -> 2 -> 1
1 -> 1 -> 1

*/


#include <cmath>
#include <vector>
#include <iostream>
#include <limits>
#include <iostream>
#include <vector>
#include <cassert>
#include <complex>
#include <cstdio>
#include <set>
#include <cstring>
#include <map>
#include <cmath>
#include <set>
#include <algorithm>
#include <queue>
#include <bitset>
#include <ctime>
#include <unordered_map>
#include <numeric>

using namespace std;
typedef long long Long;
typedef long double Double;
typedef vector<int> VI;
typedef vector<VI> VVI;
typedef pair<int,int> PII;
typedef pair<Long,Long> PLL;

int read(int &x) { return scanf("%d", &x); }
int read(int &x, int &y) { return scanf("%d%d", &x, &y); }
int read(int &x, int &y, int &z) { return scanf("%d%d%d", &x, &y, &z); }
int read(Long &x) { return scanf("%lld", &x); }
char buff[1000010];
int read(string &s) { int r = scanf("%s", buff); s = buff; return r; }

#define dlog2(n) (31-__builtin_clz(n))
template<class T>
struct SparseTable {
	int N, L;
	vector<vector<T>> table;
	SparseTable(const vector<T> &V):
			N(V.size()), L(dlog2(N)+1), table(L, vector<T>(N)){
		table[0] = V;
		for(int sz = 1; sz < L; ++sz){
			for (int i = 0; i < N; ++i) {
				if(i + (1<<sz) > N)break;
				table[sz][i] = min(table[sz-1][i], table[sz-1][i+(1<<(sz-1))]);
			}
		}
	}
	T get(int i, int j){
		int d = dlog2(j-i+1);
		return min(table[d][i], table[d][j-(1<<d)+1]);
	}
};

int MI[505][505];
#define MOD 998244353
int mul(int a, int b) {
	return 1LL*a*b%MOD;
}
int mul(int a, int b, int c) {
	return mul(mul(a, b), c);
}
int mem[502][502];
VI POS[502];
SparseTable<int> *ST;
int getMin(int i, int j) {
	return ST->get(i, j);
}
int N;
int dp(int l, int r) {
	if (l > r) return 1;
	if (mem[l][r] != -1) return mem[l][r];
	int id = getMin(l, r);
	int s = POS[id].front();
	int e = POS[id].back();
	int w = 1;
	{
		VI &P = POS[id];
		for (int i = 1; i < P.size(); ++i) {
			if (P[i-1] + 1 == P[i]) continue;
			w = mul(w, dp(P[i-1] + 1, P[i] - 1));
		}
	}
	int rw = 0;
	int lw = 0;
	for (int i = l; i <= s; ++i) {
		int t = mul(dp(l, i - 1), dp(i, s - 1));
		lw += t;
		if (lw >= MOD) lw -= MOD;
	}
	for (int j = e; j <= r; ++j) {
		int t = mul(dp(e+1, j), dp(j+1, r));
		rw += t;
		if (rw >= MOD) rw -= MOD;
	}
	return mem[l][r] = mul(lw, w, rw);
}
int VAL[1000010];
int dp2(int l, int r) {
	if (l > r) return 1;
	int cl = VAL[l], cr = VAL[r];
	if (POS[cl].front() != l) return 0;
	if (POS[cr].back() != r) return 0;
	if (mem[cl][cr] != -1) return mem[cl][cr];
	int id = getMin(l, r);
	int s = POS[id].front();
	int e = POS[id].back();
	if (s < l || r < e) return 0;
	int w = 1;
	{
		VI &P = POS[id];
		for (int i = 1; i < P.size(); ++i) {
			if (P[i-1] + 1 == P[i]) continue;
			if (POS[VAL[P[i-1]+1]].front() != P[i-1]+1) return 0;
			if (POS[VAL[P[i]-1]].back()    != P[i]-1) return 0;
			w = mul(w, dp2(P[i-1]+1, P[i]-1));
		}
	}
	int rw = 0;
	int lw = 0;
	for (int i = 0; i < N; ++i) {
		int t = 0;
		PII range(POS[i].front(), POS[i].back());
		if (l <= range.first && range.first <= s) {
			t = mul(dp2(l, range.first-1), dp2(range.first, s-1));
		}
		lw += t;
		if (lw >= MOD) lw -= MOD;
	}
	for (int i = 0; i < N; ++i) {
		int t = 0;
		PII range(POS[i].front(), POS[i].back());
		if (e <= range.second && range.second <= r) {
			t = mul(dp2(e+1, range.second), dp2(range.second+1, r));
		}
		rw += t;
		if (rw >= MOD) rw -= MOD;
	}
	return mem[l][r] = mul(lw, w, rw);
}

int main() {

	int M;
	read(N, M);
	VI V(M);
	VI IV(M);
	memset(mem, -1, sizeof(mem));
	for (int i = 0; i < M; ++i) {
		read(V[i]); V[i]--;
		VAL[i] = V[i];
		POS[V[i]].push_back(i);
	}
	set<int> ALLP; ALLP.insert(-1); ALLP.insert(M);
	ST = new SparseTable<int>(V);
	cout << dp2(0, M-1) << endl;

}


#include <cmath>
#include <vector>
#include <iostream>
#include <limits>
#include <iostream>
#include <vector>
#include <cassert>
#include <complex>
#include <cstdio>
#include <set>
#include <cstring>
#include <map>
#include <cmath>
#include <set>
#include <algorithm>
#include <queue>
#include <bitset>
#include <ctime>
#include <unordered_map>
#include <numeric>

using namespace std;
typedef long long Long;
typedef long double Double;
typedef vector<int> VI;
typedef vector<VI> VVI;
typedef pair<int,int> PII;
typedef pair<Long,Long> PLL;

int read(int &x) { return scanf("%d", &x); }
int read(int &x, int &y) { return scanf("%d%d", &x, &y); }
int read(int &x, int &y, int &z) { return scanf("%d%d%d", &x, &y, &z); }
int read(Long &x) { return scanf("%lld", &x); }
char buff[1000010];
int read(string &s) { int r = scanf("%s", buff); s = buff; return r; }

#define dlog2(n) (31-__builtin_clz(n))
template<class T>
struct SparseTable {
	int N, L;
	vector<vector<T>> table;
	SparseTable(const vector<T> &V):
			N(V.size()), L(dlog2(N)+1), table(L, vector<T>(N)){
		table[0] = V;
		for(int sz = 1; sz < L; ++sz){
			for (int i = 0; i < N; ++i) {
				if(i + (1<<sz) > N)break;
				table[sz][i] = min(table[sz-1][i], table[sz-1][i+(1<<(sz-1))]);
			}
		}
	}
	T get(int i, int j){
		int d = dlog2(j-i+1);
		return min(table[d][i], table[d][j-(1<<d)+1]);
	}
};

int MI[505][505];
#define MOD 998244353
int mul(int a, int b) {
	return 1LL*a*b%MOD;
}
int mul(int a, int b, int c) {
	return mul(mul(a, b), c);
}
int mem[502][502];
VI POS[502];
SparseTable<int> *ST;
int getMin(int i, int j) {
	return ST->get(i, j);
}
int N;
int VAL[1000010];
int dp2(int l, int r) {
	if (l > r) return 1;
	int cl = VAL[l], cr = VAL[r];
	if (POS[cl].front() != l) return 0;
	if (POS[cr].back() != r) return 0;
	if (mem[cl][cr] != -1) return mem[cl][cr];
	int id = getMin(l, r);
	int s = POS[id].front();
	int e = POS[id].back();
	if (s < l || r < e) return 0;
	int w = 1;
	{
		VI &P = POS[id];
		for (int i = 1; i < P.size(); ++i) {
			if (P[i-1] + 1 == P[i]) continue;
			if (POS[VAL[P[i-1]+1]].front() != P[i-1]+1) return 0;
			if (POS[VAL[P[i]-1]].back()    != P[i]-1) return 0;
			w = mul(w, dp2(P[i-1]+1, P[i]-1));
		}
	}
	int rw = 0;
	int lw = 0;
	for (int i = 0; i < N; ++i) {
		int t = 0;
		PII range(POS[i].front(), POS[i].back());
		if (l <= range.first && range.first <= s) {
			t = mul(dp2(l, range.first-1), dp2(range.first, s-1));
		}
		lw += t;
		if (lw >= MOD) lw -= MOD;
	}
	for (int i = 0; i < N; ++i) {
		int t = 0;
		PII range(POS[i].front(), POS[i].back());
		if (e <= range.second && range.second <= r) {
			t = mul(dp2(e+1, range.second), dp2(range.second+1, r));
		}
		rw += t;
		if (rw >= MOD) rw -= MOD;
	}
	return mem[cl][cr] = mul(lw, w, rw);
}

int main() {

	int M;
	read(N, M);
	VI V(M);
	VI IV(M);
	for (int i = 0; i < M; ++i) {
		read(V[i]); V[i]--;
		VAL[i] = V[i];
		POS[V[i]].push_back(i);
	}
	set<int> ALLP; ALLP.insert(-1); ALLP.insert(M);
	ST = new SparseTable<int>(V);
	memset(mem, -1, sizeof(mem));
	cout << dp2(0, M-1) << endl;

}

/*
3 -> 2 -> 1
3 -> 1 -> 1
2 -> 1 -> 1
1 -> 2 -> 1
1 -> 1 -> 1

*/


#include<bits/stdc++.h>
#define lli long long int
#define mod 998244353

using namespace std;

lli nnn,mmm;
lli AAA[1000100];
lli A[550],B[550];
lli tot;

void calEnd()
{
    for(lli i=1;i<=mmm;i++)
    {
        if(A[AAA[i]]==0) A[AAA[i]]=i;
        B[AAA[i]]=i;
    }

    for(lli i=1;i<=nnn;i++)
    {
        for(lli j=1;j<=nnn;j++)
        {
            if(i==j) continue;
            if(A[i]>A[j] && B[i]<B[j] && i<j) tot=1;
            if(A[i]>A[j] && A[i]<B[j] && B[i]>B[j]) tot=1;
        }
    }

    A[0]=0;
    B[0]=mmm+1;

}

lli n;
lli arr[550];
lli vrr[550];
lli dp[550][550];

lli getLeast(lli a,lli b)
{
    lli idx=a;
    for(lli i=a;i<=b;i++)
    {
        if(arr[i]<arr[idx]) idx=i;
    }
    return idx;
}

lli getVal(lli a,lli b)
{
    if(a>b) return 1;
    lli sum=(dp[a][b]*2)%mod;
    for(lli i=a+1;i<=b;i++)
    {
        lli uu=(dp[a][i-1]*dp[i][b])%mod;
        sum=(sum+uu)%mod;
    }
    //cout<<a<<" "<<b<<" "<<sum<<endl;
    return sum;
}

lli cal()
{
    memset(dp,0,sizeof(dp));
    for(lli i=1;i<=n;i++) dp[i][i]=vrr[i];
    for(lli i=2;i<=n;i++)
    {
        for(lli j=1;j<=(n-i+1);j++)
        {
            lli a=j;
            lli b=j+i-1;
            lli c=getLeast(a,b);
            lli uu=getVal(a,c-1);
            lli vv=getVal(c+1,b);
            lli ww=(uu*vv)%mod;
            dp[a][b]=(ww*vrr[c])%mod;
        }
    }

    return dp[1][n];
}

lli dfs(lli a,lli b,lli bad)
{
    //if(B[bad]==b) return 1;
    lli ans=1;
    lli con=0;
    for(lli i=a;i<=b;i++)
    {
        lli num=AAA[i];
        if(num==bad)
        {
            if(con!=0)
            {
                n=con;
                lli uuu=cal();
                ans=(ans*uuu)%mod;
            }
            con=0;
            continue;
        }
        lli j=B[num];
        lli val=dfs(i,j,num);
        con++;
        arr[con]=num;
        vrr[con]=val;
        i=j;
    }
    //cout<<a<<" "<<b<<" "<<con<<endl;
    //if(con==0) return 1;

    return ans;
}

int main()
{
    scanf("%lld%lld",&nnn,&mmm);
    for(lli i=1;i<=mmm;i++)
    {
        scanf("%lld",&AAA[i]);
    }

    calEnd();

    if(tot==0) printf("%lld\n",dfs(0,mmm+1,0));
    else printf("0\n");

    return 0;
}


#include<bits/stdc++.h>
#define lli long long int
#define mod 998244353

using namespace std;

lli nnn,mmm;
lli AAA[1000100];
lli A[550],B[550];
lli tot;

void calEnd()
{
    for(lli i=1;i<=mmm;i++)
    {
        if(A[AAA[i]]==0) A[AAA[i]]=i;
        B[AAA[i]]=i;
    }

    /*for(lli i=1;i<=nnn;i++)
    {
        for(lli j=1;j<=nnn;j++)
        {
            if(i==j) continue;
            if(A[i]>A[j] && B[i]<B[j] && i<j) tot=1;
            if(A[i]>A[j] && A[i]<B[j] && B[i]>B[j]) tot=1;
        }
    }*/

    for(int i=2;i<=nnn;i++)
    {
        for(int j=A[i];j<=B[i];j++)
        {
            if(AAA[j]<i) tot=1;
        }
    }

    A[0]=0;
    B[0]=mmm+1;

}

lli n;
lli arr[550];
lli vrr[550];
lli dp[550][550];

lli getLeast(lli a,lli b)
{
    lli idx=a;
    for(lli i=a;i<=b;i++)
    {
        if(arr[i]<arr[idx]) idx=i;
    }
    return idx;
}

lli getVal(lli a,lli b)
{
    if(a>b) return 1;
    lli sum=(dp[a][b]*2)%mod;
    for(lli i=a+1;i<=b;i++)
    {
        lli uu=(dp[a][i-1]*dp[i][b])%mod;
        sum=(sum+uu)%mod;
    }
    //cout<<a<<" "<<b<<" "<<sum<<endl;
    return sum;
}

lli cal()
{
    memset(dp,0,sizeof(dp));
    for(lli i=1;i<=n;i++) dp[i][i]=vrr[i];
    for(lli i=2;i<=n;i++)
    {
        for(lli j=1;j<=(n-i+1);j++)
        {
            lli a=j;
            lli b=j+i-1;
            lli c=getLeast(a,b);
            lli uu=getVal(a,c-1);
            lli vv=getVal(c+1,b);
            lli ww=(uu*vv)%mod;
            dp[a][b]=(ww*vrr[c])%mod;
        }
    }

    return dp[1][n];
}

lli dfs(lli a,lli b,lli bad)
{
    lli ans=1;
    lli con=0;
    lli tarr[550];
    lli tvrr[550];
    for(lli i=a;i<=b;i++)
    {
        lli num=AAA[i];
        if(num==bad)
        {
            if(con!=0)
            {
                n=con;
                for(lli l=1;l<=n;l++)
                {
                    arr[l]=tarr[l];
                    vrr[l]=tvrr[l];
                }
                lli uuu=cal();
                ans=(ans*uuu)%mod;
            }
            con=0;
            continue;
        }
        lli j=B[num];
        lli val=dfs(i,j,num);
        con++;
        tarr[con]=num;
        tvrr[con]=val;
        i=j;
    }

    return ans;
}

int main()
{
    scanf("%lld%lld",&nnn,&mmm);
    for(lli i=1;i<=mmm;i++)
    {
        scanf("%lld",&AAA[i]);
    }

    calEnd();

    if(tot==0) printf("%lld\n",dfs(0,mmm+1,0));
    else printf("0\n");

    return 0;
}


#include<bits/stdc++.h>
#define lli long long int
#define mod 998244353

using namespace std;

lli nnn,mmm;
lli AAA[1000100];
lli A[550],B[550];
lli tot;

void calEnd()
{
    for(lli i=1;i<=mmm;i++)
    {
        if(A[AAA[i]]==0) A[AAA[i]]=i;
        B[AAA[i]]=i;
    }

    for(lli i=1;i<=nnn;i++)
    {
        for(lli j=1;j<=nnn;j++)
        {
            if(i==j) continue;
            if(A[i]>A[j] && B[i]<B[j] && i<j) tot=1;
            if(A[i]>A[j] && A[i]<B[j] && B[i]>B[j]) tot=1;
        }
    }

    A[0]=0;
    B[0]=mmm+1;

}

lli n;
lli arr[550];
lli vrr[550];
lli dp[550][550];

lli getLeast(lli a,lli b)
{
    lli idx=a;
    for(lli i=a;i<=b;i++)
    {
        if(arr[i]<arr[idx]) idx=i;
    }
    return idx;
}

lli getVal(lli a,lli b)
{
    if(a>b) return 1;
    lli sum=(dp[a][b]*2)%mod;
    for(lli i=a+1;i<=b;i++)
    {
        lli uu=(dp[a][i-1]*dp[i][b])%mod;
        sum=(sum+uu)%mod;
    }
    //cout<<a<<" "<<b<<" "<<sum<<endl;
    return sum;
}

lli cal()
{
    memset(dp,0,sizeof(dp));
    for(lli i=1;i<=n;i++) dp[i][i]=vrr[i];
    for(lli i=2;i<=n;i++)
    {
        for(lli j=1;j<=(n-i+1);j++)
        {
            lli a=j;
            lli b=j+i-1;
            lli c=getLeast(a,b);
            lli uu=getVal(a,c-1);
            lli vv=getVal(c+1,b);
            lli ww=(uu*vv)%mod;
            dp[a][b]=(ww*vrr[c])%mod;
        }
    }

    return dp[1][n];
}

lli dfs(lli a,lli b,lli bad)
{
    lli ans=1;
    lli con=0;
    lli tarr[550];
    lli tvrr[550];
    for(lli i=a;i<=b;i++)
    {
        lli num=AAA[i];
        if(num==bad)
        {
            if(con!=0)
            {
                n=con;
                for(lli l=1;l<=n;l++)
                {
                    arr[l]=tarr[l];
                    vrr[l]=tvrr[l];
                }
                lli uuu=cal();
                ans=(ans*uuu)%mod;
            }
            con=0;
            continue;
        }
        lli j=B[num];
        lli val=dfs(i,j,num);
        con++;
        tarr[con]=num;
        tvrr[con]=val;
        i=j;
    }

    return ans;
}

int main()
{
    scanf("%lld%lld",&nnn,&mmm);
    for(lli i=1;i<=mmm;i++)
    {
        scanf("%lld",&AAA[i]);
    }

    calEnd();

    if(tot==0) printf("%lld\n",dfs(0,mmm+1,0));
    else printf("0\n");

    return 0;
}


#include <iostream>
#include <stdio.h>
#include <cstring>
#include <vector>
#include <algorithm>
#include <cstdlib>
#include <cmath>
#include <queue>
#include <stack>
#include <map>
#include <set>
#include <ctime>
#include <cassert>
#include <unordered_map>
#include <fstream>
#include <random>
#include <cstring>
#include <bitset>
#include <functional>
#include <tuple>
#include <complex>
#include <chrono>
#include <climits>

#define all(a) (a).begin(), (a).end()
#define sz(a) (int)(a).size()
#define pb push_back

using namespace std;

typedef long long ll;
typedef long double ld;
typedef pair<int, int> pii;
typedef pair<ll, ll> pll;
typedef unsigned int uint;
typedef unsigned long long ull;

mt19937 rnd(chrono::steady_clock::now().time_since_epoch().count());
// default_random_engine generator;
// mt19937 rnd(1);

const int P = 998244353;

void add(int &a, int b) {
    a += b;
    if (a >= P) {
        a -= P;
    }
}

void mul(int &a, int b) {
    ll c = (ll)a * b;
    c %= P;
    a = c;
}

const int MAXN = 1010;
int f[MAXN][MAXN];

int main() {
    ios_base::sync_with_stdio(false);
    cin.tie(0);
    cout.tie(0);

    // freopen("input.txt", "r", stdin);
    // freopen("output.txt", "w", stdout);

    int n, m;
    cin >> n >> m;

    vector<int> a(m);
    for (int i = 0; i < m; ++i) {
        cin >> a[i];
        --a[i];
    }

    vector<int> b = {a[0]};
    for (int i = 1; i < m; ++i) {
        if (a[i] != a[i - 1]) {
            b.push_back(a[i]);
        }
    }

    a = b;
    m = sz(a);

    if (m >= 2 * n) {
        cout << 0 << endl;
        return 0;
    }

    for (int i = 0; i < m; ++i) {
        int pos = -1;
        for (int j = 0; j < i; ++j) {
            if (a[i] == a[j]) {
                pos = j;
            }
        }
        if (pos == -1) {
            continue;
        }
        vector<int> u(n);
        vector<int> v(n);
        for (int j = 0; j < n; ++j) {
            if (pos < j && j < i) {
                u[a[j]] = 1;
            } else {
                v[a[j]] = 1 ;
            }
        }

        for (int j = 0; j < n; ++j) {
            if (u[j] && v[j]) {
                cout << 0 << endl;
                return 0;
            }
        }
    }

    for (int i = 0; i < n; ++i) {
        vector<int> ps;
        for (int j = 0; j < m; ++j) {
            if (a[j] == i) {
                ps.push_back(j);
            }
        }
        int lf = ps[0], rg = ps.back();
        // cout << i << " " << lf << " " << rg  << endl;
        for (int j = lf; j <= rg; ++j) {
            if (a[j] < i) {
                cout << 0 << endl;
                return 0;
            }
        }
    }

    // for (int i = 0; i < m; ++i) {
    //     cout << a[i] << " ";
    // }
    // cout << endl;

    for (int i = 0; i <= m; ++i) {
        f[i][i] = 1;
    }

    for (int len = 1; len <= m; ++len) {
        for (int i = 0; i + len <= m; ++i) {
            int j = i + len;
            int pos = i;
            vector<int> ps = {i};

            for (int k = i + 1; k < j; ++k) {
                if (a[pos] > a[k]) {
                    pos = k;
                    ps = {k};
                } else if (a[pos] == a[k]) {
                    ps.push_back(k);
                }
            }

            int u = 0, v = 0;

            for (int k = i; k <= ps[0]; ++k) {
                int c = f[i][k];
                mul(c, f[k][ps[0]]);
                add(u, c);
            }

            for (int k = ps.back() + 1; k <= j; ++k) {
                int c = f[ps.back() + 1][k];
                mul(c, f[k][j]);
                add(v, c);
            }

            f[i][j] = u;
            mul(f[i][j], v);

            for (int k = 0; k < sz(ps) - 1; ++k) {
                mul(f[i][j], f[ps[k] + 1][ps[k + 1]]);
            }
            // cout << i << " " << j << " " << ps[0] << " " << ps[1] << " " << f[i][j] << endl;
        }
    }

    cout << f[0][m] << endl;

    return 0;
}


#include <iostream>
#include <stdio.h>
#include <cstring>
#include <vector>
#include <algorithm>
#include <cstdlib>
#include <cmath>
#include <queue>
#include <stack>
#include <map>
#include <set>
#include <ctime>
#include <cassert>
#include <unordered_map>
#include <fstream>
#include <random>
#include <cstring>
#include <bitset>
#include <functional>
#include <tuple>
#include <complex>
#include <chrono>
#include <climits>

#define all(a) (a).begin(), (a).end()
#define sz(a) (int)(a).size()
#define pb push_back

using namespace std;

typedef long long ll;
typedef long double ld;
typedef pair<int, int> pii;
typedef pair<ll, ll> pll;
typedef unsigned int uint;
typedef unsigned long long ull;

mt19937 rnd(chrono::steady_clock::now().time_since_epoch().count());
// default_random_engine generator;
// mt19937 rnd(1);

const int P = 998244353;

void add(int &a, int b) {
    a += b;
    if (a >= P) {
        a -= P;
    }
}

void mul(int &a, int b) {
    ll c = (ll)a * b;
    c %= P;
    a = c;
}

const int MAXN = 1010;
int f[MAXN][MAXN];

int main() {
    ios_base::sync_with_stdio(false);
    cin.tie(0);
    cout.tie(0);

    // freopen("input.txt", "r", stdin);
    // freopen("output.txt", "w", stdout);

    int n, m;
    cin >> n >> m;

    vector<int> a(m);
    for (int i = 0; i < m; ++i) {
        cin >> a[i];
        --a[i];
    }

    vector<int> b = {a[0]};
    for (int i = 1; i < m; ++i) {
        if (a[i] != a[i - 1]) {
            b.push_back(a[i]);
        }
    }

    a = b;
    m = sz(a);

    if (m >= 2 * n) {
        cout << 0 << endl;
        return 0;
    }

    for (int i = 0; i < m; ++i) {
        int pos = -1;
        for (int j = 0; j < i; ++j) {
            if (a[i] == a[j]) {
                pos = j;
            }
        }
        if (pos == -1) {
            continue;
        }
        vector<int> u(n);
        vector<int> v(n);
        for (int j = 0; j < n; ++j) {
            if (pos < j && j < i) {
                u[a[j]] = 1;
            } else {
                v[a[j]] = 1 ;
            }
        }

        for (int j = 0; j < n; ++j) {
            if (u[j] && v[j]) {
                cout << 0 << endl;
                return 0;
            }
        }
    }

    // for (int i = 0; i < m; ++i) {
    //     cout << a[i] << " ";
    // }
    // cout << endl;

    for (int i = 0; i <= m; ++i) {
        f[i][i] = 1;
    }

    for (int len = 1; len <= m; ++len) {
        for (int i = 0; i + len <= m; ++i) {
            int j = i + len;
            int pos = i;
            vector<int> ps = {i};

            for (int k = i + 1; k < j; ++k) {
                if (a[pos] > a[k]) {
                    pos = k;
                    ps = {k};
                } else if (a[pos] == a[k]) {
                    ps.push_back(k);
                }
            }

            int u = 0, v = 0;

            for (int k = i; k <= ps[0]; ++k) {
                int c = f[i][k];
                mul(c, f[k][ps[0]]);
                add(u, c);
            }

            for (int k = ps.back() + 1; k <= j; ++k) {
                int c = f[ps.back() + 1][k];
                mul(c, f[k][j]);
                add(v, c);
            }

            f[i][j] = u;
            mul(f[i][j], v);

            for (int k = 0; k < sz(ps) - 1; ++k) {
                mul(f[i][j], f[ps[k] + 1][ps[k + 1]]);
            }
            // cout << i << " " << j << " " << ps[0] << " " << ps[1] << " " << f[i][j] << endl;
        }
    }

    cout << f[0][m] << endl;

    return 0;
}


#include <iostream>
#include <stdio.h>
#include <cstring>
#include <vector>
#include <algorithm>
#include <cstdlib>
#include <cmath>
#include <queue>
#include <stack>
#include <map>
#include <set>
#include <ctime>
#include <cassert>
#include <unordered_map>
#include <fstream>
#include <random>
#include <cstring>
#include <bitset>
#include <functional>
#include <tuple>
#include <complex>
#include <chrono>
#include <climits>

#define all(a) (a).begin(), (a).end()
#define sz(a) (int)(a).size()
#define pb push_back

using namespace std;

typedef long long ll;
typedef long double ld;
typedef pair<int, int> pii;
typedef pair<ll, ll> pll;
typedef unsigned int uint;
typedef unsigned long long ull;

mt19937 rnd(chrono::steady_clock::now().time_since_epoch().count());
// default_random_engine generator;
// mt19937 rnd(1);

const int P = 998244353;

void add(int &a, int b) {
    a += b;
    if (a >= P) {
        a -= P;
    }
}

void mul(int &a, int b) {
    ll c = (ll)a * b;
    c %= P;
    a = c;
}

const int MAXN = 1010;
int f[MAXN][MAXN];

int main() {
    ios_base::sync_with_stdio(false);
    cin.tie(0);
    cout.tie(0);

    // freopen("input.txt", "r", stdin);
    // freopen("output.txt", "w", stdout);

    int n, m;
    cin >> n >> m;

    vector<int> a(m);
    for (int i = 0; i < m; ++i) {
        cin >> a[i];
        --a[i];
    }

    vector<int> b = {a[0]};
    for (int i = 1; i < m; ++i) {
        if (a[i] != a[i - 1]) {
            b.push_back(a[i]);
        }
    }

    a = b;
    m = sz(a);

    if (m >= 2 * n) {
        cout << 0 << endl;
        return 0;
    }

    b = vector<int>(m);
    for (int i = 0; i < n; ++i) {
        int lf = m, rg = 0;
        for (int j = 0; j < m; ++j) {
            if (a[j] == i) {
                lf = min(lf, j);
                rg = max(rg, j);
            }
        }

        for (int j = lf; j <= rg; ++j) {
            b[j] = i;
        }
    }
    if (a != b) {
        cout << 0 << endl;
        return 0;
    }

    vector<int> lf(n, m), rg(n, 0);
    for (int i = 0; i < m; ++i) {
        lf[a[i]] = min(lf[a[i]], i);
        rg[a[i]] = i;
    }

    // for (int i = 0; i < m; ++i) {
    //     cout << a[i] << " ";
    // }
    // cout << endl;

    for (int i = 0; i <= m; ++i) {
        f[i][i] = 1;
    }

    for (int len = 1; len <= m; ++len) {
        for (int i = 0; i + len <= m; ++i) {
            int j = i + len;

            bool ok = true;
            for (int k = i; k < j; ++k) {
                if (lf[a[k]] < i || rg[a[k]] >= j) {
                    ok = false;
                }
            }

            if (!ok) {
                continue;
            }

            int pos = i;
            vector<int> ps = {i};

            for (int k = i + 1; k < j; ++k) {
                if (a[pos] > a[k]) {
                    pos = k;
                    ps = {k};
                } else if (a[pos] == a[k]) {
                    ps.push_back(k);
                }
            }

            int u = 0, v = 0;

            for (int k = i; k <= ps[0]; ++k) {
                int c = f[i][k];
                mul(c, f[k][ps[0]]);
                add(u, c);
            }

            for (int k = ps.back() + 1; k <= j; ++k) {
                int c = f[ps.back() + 1][k];
                mul(c, f[k][j]);
                add(v, c);
            }

            f[i][j] = u;
            mul(f[i][j], v);

            for (int k = 0; k < sz(ps) - 1; ++k) {
                mul(f[i][j], f[ps[k] + 1][ps[k + 1]]);
            }
            // cout << i << " " << j << " " << ps[0] << " " << ps[1] << " " << f[i][j] << endl;
        }
    }

    cout << f[0][m] << endl;

    return 0;
}