結果

問題 No.2950 Max Min Product
ユーザー kk2kk2
提出日時 2024-10-27 13:25:12
言語 C++23(gcc13)
(gcc 13.2.0 + boost 1.83.0)
結果
AC  
実行時間 1,179 ms / 3,000 ms
コード長 32,455 bytes
コンパイル時間 3,402 ms
コンパイル使用メモリ 228,660 KB
実行使用メモリ 24,416 KB
最終ジャッジ日時 2024-10-27 13:25:46
合計ジャッジ時間 33,441 ms
ジャッジサーバーID
(参考情報)
judge3 / judge1
このコードへのチャレンジ
(要ログイン)

テストケース

テストケース表示
入力 結果 実行時間
実行使用メモリ
testcase_00 AC 2 ms
6,816 KB
testcase_01 AC 2 ms
6,816 KB
testcase_02 AC 2 ms
6,820 KB
testcase_03 AC 508 ms
22,548 KB
testcase_04 AC 559 ms
22,936 KB
testcase_05 AC 524 ms
22,776 KB
testcase_06 AC 732 ms
24,324 KB
testcase_07 AC 736 ms
24,116 KB
testcase_08 AC 735 ms
24,336 KB
testcase_09 AC 356 ms
13,904 KB
testcase_10 AC 640 ms
23,712 KB
testcase_11 AC 556 ms
22,896 KB
testcase_12 AC 741 ms
24,416 KB
testcase_13 AC 756 ms
24,252 KB
testcase_14 AC 732 ms
24,300 KB
testcase_15 AC 907 ms
23,996 KB
testcase_16 AC 660 ms
22,524 KB
testcase_17 AC 729 ms
23,032 KB
testcase_18 AC 950 ms
24,280 KB
testcase_19 AC 924 ms
24,184 KB
testcase_20 AC 924 ms
24,340 KB
testcase_21 AC 414 ms
14,544 KB
testcase_22 AC 554 ms
23,016 KB
testcase_23 AC 364 ms
13,892 KB
testcase_24 AC 735 ms
24,196 KB
testcase_25 AC 732 ms
24,240 KB
testcase_26 AC 759 ms
24,264 KB
testcase_27 AC 739 ms
22,424 KB
testcase_28 AC 1,151 ms
23,964 KB
testcase_29 AC 834 ms
22,628 KB
testcase_30 AC 1,179 ms
24,272 KB
testcase_31 AC 983 ms
24,164 KB
testcase_32 AC 1,167 ms
24,324 KB
testcase_33 AC 793 ms
22,704 KB
testcase_34 AC 511 ms
13,832 KB
testcase_35 AC 771 ms
22,676 KB
testcase_36 AC 1,079 ms
24,184 KB
testcase_37 AC 1,076 ms
24,320 KB
testcase_38 AC 1,073 ms
24,240 KB
testcase_39 AC 2 ms
6,816 KB
権限があれば一括ダウンロードができます

ソースコード

diff #

#ifndef MODINT_HPP
#define MODINT_HPP 1

#include <cassert>
#include <iostream>
#include <type_traits>
#include <utility>

#ifndef TYPE_TRAITS_HPP
#define TYPE_TRAITS_HPP 1


#include <istream>
#include <ostream>
#include <type_traits>

namespace kk2 {

template <typename T>
using is_signed_int128 = typename std::conditional<std::is_same<T, __int128_t>::value
                                                       or std::is_same<T, __int128>::value,
                                                   std::true_type,
                                                   std::false_type>::type;

template <typename T>
using is_unsigned_int128 =
    typename std::conditional<std::is_same<T, __uint128_t>::value
                                  or std::is_same<T, unsigned __int128>::value,
                              std::true_type,
                              std::false_type>::type;

template <typename T>
using is_integral =
    typename std::conditional<std::is_integral<T>::value or is_signed_int128<T>::value
                                  or is_unsigned_int128<T>::value,
                              std::true_type,
                              std::false_type>::type;

template <typename T>
using is_signed = typename std::conditional<std::is_signed<T>::value or is_signed_int128<T>::value,
                                            std::true_type,
                                            std::false_type>::type;

template <typename T>
using is_unsigned =
    typename std::conditional<std::is_unsigned<T>::value or is_unsigned_int128<T>::value,
                              std::true_type,
                              std::false_type>::type;

template <typename T>
using make_unsigned_int128 =
    typename std::conditional<std::is_same<T, __int128_t>::value, __uint128_t, unsigned __int128>;

template <typename T>
using to_unsigned =
    typename std::conditional<is_signed_int128<T>::value,
                              make_unsigned_int128<T>,
                              typename std::conditional<std::is_signed<T>::value,
                                                        std::make_unsigned<T>,
                                                        std::common_type<T>>::type>::type;

template <typename T> using is_integral_t = std::enable_if_t<is_integral<T>::value>;
template <typename T> using is_signed_t = std::enable_if_t<is_signed<T>::value>;
template <typename T> using is_unsigned_t = std::enable_if_t<is_unsigned<T>::value>;


template <typename T>
using is_function_pointer =
    typename std::conditional<std::is_pointer_v<T> && std::is_function_v<std::remove_pointer_t<T>>,
                              std::true_type,
                              std::false_type>::type;

template <typename T, std::enable_if_t<is_function_pointer<T>::value> * = nullptr>
struct is_two_args_function_pointer : std::false_type {};

template <typename R, typename T1, typename T2>
struct is_two_args_function_pointer<R (*)(T1, T2)> : std::true_type {};

template <typename T>
using is_two_args_function_pointer_t = std::enable_if_t<is_two_args_function_pointer<T>::value>;

namespace type_traits {

struct istream_tag {};

struct ostream_tag {};

} // namespace type_traits

template <typename T> using is_standard_istream = std::is_same<T, std::istream>;
template <typename T> using is_standard_ostream = std::is_same<T, std::ostream>;
template <typename T> using is_user_defined_istream = std::is_base_of<type_traits::istream_tag, T>;
template <typename T> using is_user_defined_ostream = std::is_base_of<type_traits::ostream_tag, T>;

template <typename T>
using is_istream =
    typename std::conditional<is_standard_istream<T>::value || is_user_defined_istream<T>::value,
                              std::true_type,
                              std::false_type>::type;

template <typename T>
using is_ostream =
    typename std::conditional<is_standard_ostream<T>::value || is_user_defined_ostream<T>::value,
                              std::true_type,
                              std::false_type>::type;

template <typename T> using is_istream_t = std::enable_if_t<is_istream<T>::value>;
template <typename T> using is_ostream_t = std::enable_if_t<is_ostream<T>::value>;


} // namespace kk2

#endif // TYPE_TRAITS_HPP

// #include "../type_traits/type_traits.hpp"

namespace kk2 {

template <int p> struct ModInt {
    using mint = ModInt;

  public:
    static int Mod;

    constexpr static unsigned int getmod() {
        if (p > 0) return p;
        else return Mod;
    }

    static void setmod(int Mod_) {
        assert(1 <= Mod_);
        Mod = Mod_;
    }

    static mint raw(int v) {
        mint x;
        x._v = v;
        return x;
    }

    constexpr ModInt() : _v(0) {}

    template <class T, is_integral_t<T> * = nullptr> constexpr ModInt(T v) {
        if constexpr (is_signed<T>::value) {
            v %= getmod();
            if (v < 0) v += getmod();
            _v = v;
        } else if constexpr (is_unsigned<T>::value) {
            _v = v %= getmod();
        } else {
            ModInt();
        }
    }

    unsigned int val() const { return _v; }

    mint &operator++() {
        _v++;
        if (_v == getmod()) _v = 0;
        return *this;
    }

    mint &operator--() {
        if (_v == 0) _v = getmod();
        _v--;
        return *this;
    }

    mint operator++(int) {
        mint result = *this;
        ++*this;
        return result;
    }

    mint operator--(int) {
        mint result = *this;
        --*this;
        return result;
    }

    mint &operator+=(const mint &rhs) {
        _v += rhs._v;
        if (_v >= getmod()) _v -= getmod();
        return *this;
    }

    mint &operator-=(const mint &rhs) {
        _v += getmod() - rhs._v;
        if (_v >= getmod()) _v -= getmod();
        return *this;
    }

    mint &operator*=(const mint &rhs) {
        unsigned long long z = _v;
        z *= rhs._v;
        z %= getmod();
        _v = z;
        return *this;
    }

    mint &operator/=(const mint &rhs) { return *this = *this * rhs.inv(); }

    mint operator+() const { return *this; }

    mint operator-() const { return mint() - *this; }

    mint pow(long long n) const {
        assert(0 <= n);
        mint x = *this, r = 1;
        while (n) {
            if (n & 1) r *= x;
            x *= x;
            n >>= 1;
        }
        return r;
    }

    mint inv() const {
        long long s = getmod(), t = _v;
        long long m0 = 0, m1 = 1;

        while (t) {
            long long u = s / t;
            s -= t * u;
            m0 -= m1 * u;

            std::swap(s, t);
            std::swap(m0, m1);
        }
        if (m0 < 0) m0 += getmod() / s;
        return m0;
    }

    friend mint operator+(const mint &lhs, const mint &rhs) { return mint(lhs) += rhs; }

    friend mint operator-(const mint &lhs, const mint &rhs) { return mint(lhs) -= rhs; }

    friend mint operator*(const mint &lhs, const mint &rhs) { return mint(lhs) *= rhs; }

    friend mint operator/(const mint &lhs, const mint &rhs) { return mint(lhs) /= rhs; }

    friend bool operator==(const mint &lhs, const mint &rhs) { return lhs._v == rhs._v; }

    friend bool operator!=(const mint &lhs, const mint &rhs) { return lhs._v != rhs._v; }

    template <class OStream, is_ostream_t<OStream> * = nullptr>
    friend OStream &operator<<(OStream &os, const mint &mint_) {
        os << mint_._v;
        return os;
    }

    template <class IStream, is_istream_t<IStream> * = nullptr>
    friend IStream &operator>>(IStream &is, mint &mint_) {
        long long x;
        is >> x;
        mint_ = mint(x);
        return is;
    }

  private:
    unsigned int _v;
};

template <int p> int ModInt<p>::Mod = 998244353;


using mint998 = ModInt<998244353>;
using mint107 = ModInt<1000000007>;

} // namespace kk2

#endif // MODINT_HPP

// #include <kk2/modint/modint.hpp>
#ifndef LAZY_HPP
#define LAZY_HPP 1

#include <cassert>
#include <functional>
#include <vector>

namespace kk2 {

template <class S,
          S (*op)(S, S),
          S (*e)(),
          class F,
          S (*mapping)(F, S),
          F (*composition)(F, F),
          F (*id)()>
struct LazySegTree {
  public:
    LazySegTree() : LazySegTree(0) {}

    LazySegTree(int n) : LazySegTree(std::vector<S>(n, e())) {}

    template <class... Args>
    LazySegTree(int n, Args... args) : LazySegTree(std::vector<S>(n, S(args...))) {}

    LazySegTree(const std::vector<S> &v) : _n(int(v.size())) {
        log = 0;
        while ((1ll << log) < _n) log++;
        size = 1 << log;
        d = std::vector<S>(2 * size, e());
        lz = std::vector<F>(size, id());
        for (int i = 0; i < _n; i++) d[size + i] = v[i];
        for (int i = size - 1; i >= 1; i--) { update(i); }
    }

    using Monoid = S;

    static S Op(S l, S r) { return op(l, r); }

    static S MonoidUnit() { return e(); }

    using Hom = F;

    static S Map(F f, S x) { return mapping(f, x); }

    static F Composition(F l, F r) { return composition(l, r); }

    static F HomUnit() { return id(); }

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

    template <class... Args> void emplace_set(int p, Args... args) { set(p, S(args...)); }

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

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

        l += size;
        r += size;

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

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

        return op(sml, smr);
    }

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

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

    template <class... Args> void emplace_apply_point(int p, Args... args) { apply(p, F(args...)); }

    void apply(int l, int r, F f) {
        assert(0 <= l && l <= r && r <= _n);
        if (l == r) return;

        l += size;
        r += size;

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

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

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

    template <class... Args> void emplace_apply_range(int l, int r, Args... args) {
        apply(l, r, F(args...));
    }

    template <bool (*g)(S)> int max_right(int l) {
        return max_right(l, [](S x) { return g(x); });
    }

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

    template <bool (*g)(S)> int min_left(int r) {
        return min_left(r, [](S x) { return g(x); });
    }

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

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

    void update(int k) { d[k] = op(d[2 * k], d[2 * k + 1]); }

    void all_apply(int k, F f) {
        d[k] = mapping(f, d[k]);
        if (k < size) lz[k] = composition(f, lz[k]);
    }

    void push(int k) {
        all_apply(2 * k, lz[k]);
        all_apply(2 * k + 1, lz[k]);
        lz[k] = id();
    }
};

} // namespace kk2

#endif // LAZY_HPP

// #include <kk2/segment_tree/lazy.hpp>
#ifndef SEGMENT_TREE_UTILITY_UPDATEMAX_HPP
#define SEGMENT_TREE_UTILITY_UPDATEMAX_HPP 1

#ifndef MATH_HOMOMORPHISM_UPDATE_HPP
#define MATH_HOMOMORPHISM_UPDATE_HPP 1

#include <iostream>

namespace kk2 {

namespace homomorphism {

template <class S> struct Update {
    S a;
    bool id;

    constexpr Update() : a(S()), id(true) {}

    constexpr Update(S a_, bool id_ = false) : a(a_), id(id_) {}

    operator S() const { return a; }

    template <class OStream>
    friend OStream &operator<<(OStream &os, const Update &update) {
        if (update.id) os << "id";
        else os << update.a;
        return os;
    }
};

template <class S, class T> constexpr T UpdateMap(Update<S> f, T x) {
    return f.id ? x : x.update(f.a);
}

template <class S> constexpr Update<S> UpdateComposition(Update<S> l, Update<S> r) {
    if (l.id) return r;
    return l;
}

template <class S> Update<S> UpdateUnit() {
    constexpr static Update<S> e = Update<S>();
    return e;
}

} // namespace homomorphism

} // namespace kk2

#endif // MATH_HOMOMORPHISM_UPDATE_HPP

// #include "../../math/homomorphism/update.hpp"
#ifndef MATH_MONOID_MAX_HPP
#define MATH_MONOID_MAX_HPP 1

#include <algorithm>
#include <iostream>
#include <vector>

namespace kk2 {

namespace monoid {

template <class S> struct Max {
    S a;
    bool minf;

    constexpr Max() : a(S()), minf(true) {}

    constexpr Max(S a_, bool minf_ = false) : a(a_), minf(minf_) {}

    operator S() const { return a; }

    template <class OStream>
    friend OStream &operator<<(OStream &os, const Max &max) {
        if (max.minf) os << "minf";
        else os << max.a;
        return os;
    }

    template <class IStream>
    friend IStream &operator>>(IStream &is, Max &max) {
        is >> max.a;
        max.minf = false;
        return is;
    }

    constexpr Max &operator=(const S &rhs) {
        a = rhs;
        minf = false;
        return *this;
    }

    constexpr Max &add(const S &rhs) {
        if (minf) return *this;
        a += rhs;
        return *this;
    }

    constexpr Max &update(const S &rhs) {
        a = rhs;
        minf = false;
        return *this;
    }

    constexpr bool is_minf() { return minf; }
};

template <class S> constexpr Max<S> MaxOp(Max<S> l, Max<S> r) {
    if (r.minf) return l;
    if (l.minf) return r;
    l.a = std::max(l.a, r.a);
    return l;
}

template <class S> Max<S> MaxUnit() {
    constexpr static Max<S> e = Max<S>();
    return e;
}

} // namespace monoid

template <class S, class... Args>
std::vector<monoid::Max<S>> GetVecMax(int n, Args... args) {
    return std::vector<monoid::Max<S>>(n, monoid::Max<S>(args...));
}

template <class S, class... Args>
std::vector<std::vector<monoid::Max<S>>> GetVecMax2D(int h, int w, Args... args) {
    return std::vector<std::vector<monoid::Max<S>>>(h, GetVecMax<S>(w, args...));
}

} // namespace kk2

#endif // MATH_MONOID_MAX_H

// #include "../../math/monoid/max.hpp"
// #include "../lazy.hpp"

namespace kk2 {

template <class S>
using UpdateMax = LazySegTree<monoid::Max<S>,
                              monoid::MaxOp<S>,
                              monoid::MaxUnit<S>,
                              homomorphism::Update<S>,
                              homomorphism::UpdateMap<S, monoid::Max<S>>,
                              homomorphism::UpdateComposition<S>,
                              homomorphism::UpdateUnit<S>>;

} // namespace kk2

#endif // SEGMENT_TREE_UTILITY_UPDATEMAX_HPP

// #include <kk2/segment_tree/utility/updatemax.hpp>
#ifndef TEMPLATE
#define TEMPLATE 1

// #pragma GCC optimize("O3,unroll-loops")

// #include <bits/stdc++.h>
#include <algorithm>
#include <array>
#include <bitset>
#include <cassert>
#include <chrono>
#include <cmath>
#include <cstring>
#include <deque>
#include <fstream>
#include <functional>
#include <iomanip>
#include <iostream>
#include <iterator>
#include <limits>
#include <map>
#include <numeric>
#include <optional>
#include <queue>
#include <random>
#include <set>
#include <sstream>
#include <stack>
#include <string>
#include <tuple>
#include <type_traits>
#include <unordered_map>
#include <unordered_set>
#include <utility>
#include <vector>

// #include "../type_traits/type_traits.hpp"
#ifndef TEMPLATE_FASTIO_HPP
#define TEMPLATE_FASTIO_HPP 1

#include <cctype>
#include <cstdint>
#include <cstdio>
#include <fstream>
#include <iostream>
#include <string>

// #include "../type_traits/type_traits.hpp"

namespace kk2 {

namespace fastio {

#define INPUT_FILE "in.txt"
#define OUTPUT_FILE "out.txt"

struct Scanner : type_traits::istream_tag {
  private:
    static constexpr size_t INPUT_BUF = 1 << 17;
    size_t pos = 0, end = 0;
    static char buf[INPUT_BUF];
    FILE *fp;

  public:
    Scanner() : fp(stdin) {}

    Scanner(const char *file) : fp(fopen(file, "r")) {}

    ~Scanner() {
        if (fp != stdin) fclose(fp);
    }

    char now() {
        if (pos == end) {
            while (!(end = fread(buf, 1, INPUT_BUF, fp))) {}
            if (end != INPUT_BUF) buf[end] = '\0';
            pos = 0;
        }
        return buf[pos];
    }

    void skip_space() {
        while (isspace(now())) ++pos;
    }

    template <class T, is_unsigned_t<T> * = nullptr> T next_unsigned_integral() {
        skip_space();
        T res{};
        while (isdigit(now())) {
            res = res * 10 + (now() - '0');
            ++pos;
        }
        return res;
    }

    template <class T, is_signed_t<T> * = nullptr> T next_signed_integral() {
        skip_space();
        if (now() == '-') {
            ++pos;
            return T(-next_unsigned_integral<typename to_unsigned<T>::type>());
        } else return (T)next_unsigned_integral<typename to_unsigned<T>::type>();
    }

    char next_char() {
        skip_space();
        auto res = now();
        ++pos;
        return res;
    }

    std::string next_string() {
        skip_space();
        std::string res;
        while (true) {
            char c = now();
            if (isspace(c) or c == '\0') break;
            res.push_back(now());
            ++pos;
        }
        return res;
    }

    template <class T, is_unsigned_t<T> * = nullptr> Scanner &operator>>(T &x) {
        x = next_unsigned_integral<T>();
        return *this;
    }

    template <class T, is_signed_t<T> * = nullptr> Scanner &operator>>(T &x) {
        x = next_signed_integral<T>();
        return *this;
    }

    Scanner &operator>>(char &x) {
        x = next_char();
        return *this;
    }

    Scanner &operator>>(std::string &x) {
        x = next_string();
        return *this;
    }
};

struct endl_struct_t {};

struct Printer : type_traits::ostream_tag {
  private:
    static char helper[10000][5];
    static char leading_zero[10000][5];
    constexpr static size_t OUTPUT_BUF = 1 << 17;
    static char buf[OUTPUT_BUF];
    size_t pos = 0;
    FILE *fp;

    template <class T> static constexpr void div_mod(T &a, T &b, T mod) {
        a = b / mod;
        b -= a * mod;
    }

    static void init() {
        buf[0] = '\0';
        for (size_t i = 0; i < 10000; ++i) {
            leading_zero[i][0] = i / 1000 + '0';
            leading_zero[i][1] = i / 100 % 10 + '0';
            leading_zero[i][2] = i / 10 % 10 + '0';
            leading_zero[i][3] = i % 10 + '0';
            leading_zero[i][4] = '\0';

            size_t j = 0;
            if (i >= 1000) helper[i][j++] = i / 1000 + '0';
            if (i >= 100) helper[i][j++] = i / 100 % 10 + '0';
            if (i >= 10) helper[i][j++] = i / 10 % 10 + '0';
            helper[i][j++] = i % 10 + '0';
            helper[i][j] = '\0';
        }
    }

  public:
    Printer() : fp(stdout) { init(); }

    Printer(const char *file) : fp(fopen(file, "w")) { init(); }

    ~Printer() {
        write();
        if (fp != stdout) fclose(fp);
    }

    void write() {
        fwrite(buf, 1, pos, fp);
        pos = 0;
    }

    void flush() {
        write();
        fflush(fp);
    }

    void put_char(char c) {
        if (pos == OUTPUT_BUF) write();
        buf[pos++] = c;
    }

    void put_cstr(const char *s) {
        while (*s) put_char(*(s++));
    }

    void put_u32(uint32_t x) {
        uint32_t y;
        if (x >= 100000000) { // 10^8
            div_mod<uint32_t>(y, x, 100000000);
            put_cstr(helper[y]);
            div_mod<uint32_t>(y, x, 10000);
            put_cstr(leading_zero[y]);
            put_cstr(leading_zero[x]);
        } else if (x >= 10000) { // 10^4
            div_mod<uint32_t>(y, x, 10000);
            put_cstr(helper[y]);
            put_cstr(leading_zero[x]);
        } else put_cstr(helper[x]);
    }

    void put_i32(int32_t x) {
        if (x < 0) {
            put_char('-');
            put_u32(-x);
        } else put_u32(x);
    }

    void put_u64(uint64_t x) {
        uint64_t y;
        if (x >= 1000000000000ull) { // 10^12
            div_mod<uint64_t>(y, x, 1000000000000ull);
            put_u32(y);
            div_mod<uint64_t>(y, x, 100000000ull);
            put_cstr(leading_zero[y]);
            div_mod<uint64_t>(y, x, 10000ull);
            put_cstr(leading_zero[y]);
            put_cstr(leading_zero[x]);
        } else if (x >= 10000ull) { // 10^4
            div_mod<uint64_t>(y, x, 10000ull);
            put_u32(y);
            put_cstr(leading_zero[x]);
        } else put_cstr(helper[x]);
    }

    void put_i64(int64_t x) {
        if (x < 0) {
            put_char('-');
            put_u64(-x);
        } else put_u64(x);
    }

    void put_u128(__uint128_t x) {
        constexpr static __uint128_t pow10_10 = 10000000000ull;
        constexpr static __uint128_t pow10_20 = pow10_10 * pow10_10;

        __uint128_t y;
        if (x >= pow10_20) { // 10^20
            div_mod<__uint128_t>(y, x, pow10_20);
            put_u64(uint64_t(y));
            div_mod<__uint128_t>(y, x, __uint128_t(10000000000000000ull));
            put_cstr(leading_zero[y]);
            div_mod<__uint128_t>(y, x, __uint128_t(1000000000000ull));
            put_cstr(leading_zero[y]);
            div_mod<__uint128_t>(y, x, __uint128_t(100000000ull));
            put_cstr(leading_zero[y]);
            div_mod<__uint128_t>(y, x, __uint128_t(10000ull));
            put_cstr(leading_zero[y]);
            put_cstr(leading_zero[x]);
        } else if (x >= __uint128_t(10000)) { // 10^4
            div_mod<__uint128_t>(y, x, __uint128_t(10000));
            put_u64(uint64_t(y));
            put_cstr(leading_zero[x]);
        } else put_cstr(helper[x]);
    }

    void put_i128(__int128_t x) {
        if (x < 0) {
            put_char('-');
            put_u128(-x);
        } else put_u128(x);
    }

    template <class T, is_unsigned_t<T> * = nullptr> Printer &operator<<(T x) {
        if constexpr (sizeof(T) <= 4) put_u32(x);
        else if constexpr (sizeof(T) <= 8) put_u64(x);
        else put_u128(x);
        return *this;
    }

    template <class T, is_signed_t<T> * = nullptr> Printer &operator<<(T x) {
        if constexpr (sizeof(T) <= 4) put_i32(x);
        else if constexpr (sizeof(T) <= 8) put_i64(x);
        else put_i128(x);
        return *this;
    }

    Printer &operator<<(char x) {
        put_char(x);
        return *this;
    }

    Printer &operator<<(const std::string &x) {
        for (char c : x) put_char(c);
        return *this;
    }

    Printer &operator<<(const char *x) {
        put_cstr(x);
        return *this;
    }

    // std::cout << std::endl; は関数ポインタを渡しているらしい
    Printer &operator<<(endl_struct_t) {
        put_char('\n');
        flush();
        return *this;
    }
};

char Scanner::buf[Scanner::INPUT_BUF];
char Printer::buf[Printer::OUTPUT_BUF];
char Printer::helper[10000][5];
char Printer::leading_zero[10000][5];

} // namespace fastio

#if defined(INTERACTIVE) || defined(USE_STDIO)
auto &kin = std::cin;
auto &kout = std::cout;
auto (*kendl)(std::ostream &) = std::endl<char, std::char_traits<char>>;
#elif defined(KK2)
fastio::Scanner kin(INPUT_FILE);
fastio::Printer kout(OUTPUT_FILE);
fastio::endl_struct_t kendl;
#else
fastio::Scanner kin;
fastio::Printer kout;
fastio::endl_struct_t kendl;
#endif

} // namespace kk2

#endif // TEMPLATE_FASTIO_HPP

// #include "fastio.hpp"

using u32 = unsigned int;
using i64 = long long;
using u64 = unsigned long long;
using i128 = __int128_t;
using u128 = __uint128_t;

using pi = std::pair<int, int>;
using pl = std::pair<i64, i64>;
using pil = std::pair<int, i64>;
using pli = std::pair<i64, int>;

template <class T> using vc = std::vector<T>;
template <class T> using vvc = std::vector<vc<T>>;
template <class T> using vvvc = std::vector<vvc<T>>;
template <class T> using vvvvc = std::vector<vvvc<T>>;

template <class T> using pq = std::priority_queue<T>;
template <class T> using pqi = std::priority_queue<T, std::vector<T>, std::greater<T>>;

template <class T> constexpr T infty = 0;
template <> constexpr int infty<int> = (1 << 30) - 123;
template <> constexpr i64 infty<i64> = (1ll << 62) - (1ll << 31);
template <> constexpr i128 infty<i128> = (i128(1) << 126) - (i128(1) << 63);
template <> constexpr u32 infty<u32> = infty<int>;
template <> constexpr u64 infty<u64> = infty<i64>;
template <> constexpr u128 infty<u128> = infty<i128>;
template <> constexpr double infty<double> = infty<i64>;
template <> constexpr long double infty<long double> = infty<i64>;

constexpr int mod = 998244353;
constexpr int modu = 1e9 + 7;
constexpr long double PI = 3.14159265358979323846;

namespace kk2 {

template <class T, class... Sizes> auto make_vector(int first, Sizes... sizes) {
    if constexpr (sizeof...(sizes) == 0) {
        return std::vector<T>(first);
    } else {
        return std::vector<decltype(make_vector(sizes...))>(first, make_vector(sizes...));
    }
}

template <class T, class U> void fill_all(std::vector<T> &v, const U &x) {
    std::fill(std::begin(v), std::end(v), T(x));
}

template <class T, class U> void fill_all(std::vector<std::vector<T>> &v, const U &x) {
    for (auto &u : v) fill_all(u, x);
}

} // namespace kk2

template <class T, class S> inline bool chmax(T &a, const S &b) {
    return (a < b ? a = b, 1 : 0);
}

template <class T, class S> inline bool chmin(T &a, const S &b) {
    return (a > b ? a = b, 1 : 0);
}

#define rep1(a) for (i64 _ = 0; _ < (i64)(a); ++_)
#define rep2(i, a) for (i64 i = 0; i < (i64)(a); ++i)
#define rep3(i, a, b) for (i64 i = (a); i < (i64)(b); ++i)
#define repi2(i, a) for (i64 i = (a) - 1; i >= 0; --i)
#define repi3(i, a, b) for (i64 i = (a) - 1; i >= (i64)(b); --i)
#define overload3(a, b, c, d, ...) d
#define rep(...) overload3(__VA_ARGS__, rep3, rep2, rep1)(__VA_ARGS__)
#define repi(...) overload3(__VA_ARGS__, repi3, repi2, rep1)(__VA_ARGS__)

#define fi first
#define se second
#define all(p) std::begin(p), std::end(p)

using kk2::kendl;
using kk2::kin;
using kk2::kout;

struct IoSetUp {
    IoSetUp() {
        std::cin.tie(nullptr);
        std::ios::sync_with_stdio(false);
    }
} iosetup;

template <class OStream, class T, class U, kk2::is_ostream_t<OStream> * = nullptr>
OStream &operator<<(OStream &os, const std::pair<T, U> &p) {
    os << p.first << ' ' << p.second;
    return os;
}

template <class IStream, class T, class U, kk2::is_istream_t<IStream> * = nullptr>
IStream &operator>>(IStream &is, std::pair<T, U> &p) {
    is >> p.first >> p.second;
    return is;
}

template <class OStream, class T, kk2::is_ostream_t<OStream> * = nullptr>
OStream &operator<<(OStream &os, const std::vector<T> &v) {
    for (int i = 0; i < (int)v.size(); i++) { os << v[i] << (i + 1 == (int)v.size() ? "" : " "); }
    return os;
}

template <class IStream, class T, kk2::is_istream_t<IStream> * = nullptr>
IStream &operator>>(IStream &is, std::vector<T> &v) {
    for (auto &x : v) is >> x;
    return is;
}

void Yes(bool b = 1) {
    kout << (b ? "Yes\n" : "No\n");
}

void No(bool b = 1) {
    kout << (b ? "No\n" : "Yes\n");
}

void YES(bool b = 1) {
    kout << (b ? "YES\n" : "NO\n");
}

void NO(bool b = 1) {
    kout << (b ? "NO\n" : "YES\n");
}

void yes(bool b = 1) {
    kout << (b ? "yes\n" : "no\n");
}

void no(bool b = 1) {
    kout << (b ? "no\n" : "yes\n");
}

#endif // TEMPLATE

// #include <kk2/template/template.hpp>
using namespace std;

struct S {
    int a, b;
    kk2::mint998 sum_a, sum_b, sum_ab;
    int size;
};

S op(S l, S r) {
    l.sum_a += r.sum_a;
    l.sum_b += r.sum_b;
    l.sum_ab += r.sum_ab;
    l.size += r.size;
    return l;
}

S e() {
    return S{0, 0, 0, 0, 0, 0};
}

struct F {
    int upd_a, upd_b;
    bool unit_a, unit_b;
};

S mapping(F f, S x) {
    if (f.unit_a and f.unit_b) return x;
    else if (f.unit_a) {
        x.b = f.upd_b;
        x.sum_b = i64(x.b) * x.size;
        x.sum_ab = x.sum_a * x.b;
        return x;
    }
    else if (f.unit_b) {
        x.a = f.upd_a;
        x.sum_a = i64(x.a) * x.size;
        x.sum_ab = x.sum_b * x.a;
        return x;
    }
    else {
        x.a = f.upd_a;
        x.b = f.upd_b;
        x.sum_a = i64(x.a) * x.size;
        x.sum_b = i64(x.b) * x.size;
        x.sum_ab = kk2::mint998(x.a) * x.b * x.size;
        return x;
    }
}

F composition(F l, F r) {
    if (l.unit_a) {
        l.upd_a = r.upd_a;
        l.unit_a = r.unit_a;
    }
    if (l.unit_b) {
        l.upd_b = r.upd_b;
        l.unit_b = r.unit_b;
    }
    return l;
}

F id() {
    return F{0, 0, true, true};
}

void solve() {
    int n;
    kin >> n;
    vc<int> a(n);
    kin >> a;

    kk2::LazySegTree<S, op, e, F, mapping, composition, id> seg(n);

    kk2::mint998 res = 0, sum = 0;
    rep (i, n) {
        if (i == 0) {
            sum += 1ll * a[i] * a[i];
            res += sum;
            seg.set(i, S{a[i], a[i], a[i], a[i], 1ll * a[i] * a[i], 1});
            continue;
        }
        if (a[i] > a[i - 1]) {
            int idx = seg.min_left(i, [&](S x) -> bool {
                if (!x.size) return true;
                return x.a < a[i];
            });
            sum -= seg.prod(idx, i).sum_ab;
            seg.apply(idx, i, F{a[i], 0, false, true});
            seg.set(i, S{a[i], a[i], a[i], a[i], 1ll * a[i] * a[i], 1});
            sum += seg.prod(idx, i + 1).sum_ab;
            res += sum;
        }
        else {
            int idx = seg.min_left(i, [&](S x) -> bool {
                if (!x.size) return true;
                return x.b > a[i];
            });
            sum -= seg.prod(idx, i).sum_ab;
            seg.apply(idx, i, F{0, a[i], true, false});
            seg.set(i, S{a[i], a[i], a[i], a[i], 1ll * a[i] * a[i], 1});
            sum += seg.prod(idx, i + 1).sum_ab;
            res += sum;
        }
        // rep (j, i + 1) {
        //     S s = seg.get(j);
        //     kout << s.a << " " << s.b << " " << s.sum_ab << " " << s.size << kendl;
        // }
        // kout << res << kendl;
    }
    kout << res << kendl;
}

int main() {
    int t = 1;
    // kin >> t;
    rep (t) solve();

    return 0;
}

// converted!!
0