Submission #61745961


Source Code Expand

#include <cassert>
#include <algorithm>
#include <vector>

template<typename Idx, typename S, S (*op)(S, S), S (*e)(), typename F, S (*mapping)(F, S, Idx), F (*composition)(F, F), F (*id)()>
struct segtree_lazy_sparse {
  private:
    
    static constexpr S pow_monoid(S a, Idx k) {
        S b = e();
        while (k) {
            if (k & 1) b = op(b, a);
            a = op(a, a);
            k >>= 1;
        }
        return b;
    }

    struct node {
        int h;
        Idx lx, rx, Lx, Rx;
        node *l, *r;
        S val, sum, sum_subtree;
        F lz;
        node(Idx _lx, Idx _rx, S _val) : lx(_lx), rx(_rx), Lx(_lx), Rx(_rx), l(nullptr), r(nullptr), 
            val(_val), sum(pow_monoid(_val, rx - lx)), sum_subtree(sum), lz(id()) {}
        int factor() const { return (l ? l->h : 0) - (r ? r->h : 0); }
    };

    static void update(node *v) {
        v->h = 1;
        v->Lx = v->lx;
        v->Rx = v->rx;
        v->sum_subtree = v->sum;
        if (v->l) {
            v->h = v->l->h + 1;
            v->Lx = v->l->Lx;
            v->sum_subtree = op(v->l->sum_subtree, v->sum_subtree);
        }
        if (v->r) {
            v->h = std::max(v->h, v->r->h + 1);
            v->Rx = v->r->Rx;
            v->sum_subtree = op(v->sum_subtree, v->r->sum_subtree);
        }
    } 

    static void push_down(node *v) {
        if (v->lz != id()) {
            if (v->l) all_apply(v->l, v->lz);
            if (v->r) all_apply(v->r, v->lz);
            v->lz = id();
        }
    }

    static void all_apply(node *v, F lz) {
        v->lz = composition(lz, v->lz);
        v->val = mapping(lz, v->val, 1);
        v->sum = mapping(lz, v->sum, v->rx - v->lx);
        v->sum_subtree = mapping(lz, v->sum_subtree, v->Rx - v->Lx);
    }

    static node *rotate_right(node *v) {
        node *l = v->l;
        v->l = l->r;
        l->r = v;
        update(v);
        update(l);
        return l;
    }
    
    static node *rotate_left(node *v) {
        node *r = v->r;
        v->r = r->l;
        r->l = v;
        update(v);
        update(r);
        return r;
    }

    static node *balance(node *v) {
        int bf = v->factor();
        if (bf == 2) {
            if (v->l->factor() == -1) {
                v->l = rotate_left(v->l);
                update(v);
            }
            return rotate_right(v);
        } else if(bf == -2) {
            if (v->r->factor() == 1) {
                v->r = rotate_right(v->r);
                update(v);
            }
            return rotate_left(v);
        }
        return v;
    }

    static node *insert_leftmost(node *v, node *u) {
        if (!v) return u;
        push_down(v);
        v->l = insert_leftmost(v->l, u);
        update(v);
        return balance(v);
    }

    static node *insert_rightmost(node *v, node *u) {
        if (!v) return u;
        push_down(v);
        v->r = insert_rightmost(v->r, u);
        update(v);
        return balance(v);
    }

    // vと[l, r)が交差する時に使える
    // [v->lx, l), [r, v-rx)を切り取って返す
    static std::pair<node*, node*> split(node *v, Idx l, Idx r) {
        l = std::max(l, v->lx);
        r = std::min(r, v->rx);
        assert(l < r);
        node *a = nullptr, *c = nullptr;
        if (v->lx < l) a = new node(v->lx, l, v->val);
        if (r < v->rx) c = new node(r, v->rx, v->val);
        v->lx = l, v->rx = r;
        v->sum = pow_monoid(v->val, r - l);
        return {a, c};
    }

    node *root;

  public:
    segtree_lazy_sparse(Idx minf, Idx inf) : root(new node(minf, inf, e())) {}

    void set(Idx p, S x) {
        auto dfs = [&](auto &&dfs, node *v) -> node* {
            if (!v || p < v->Lx || v->Rx <= p) return v;
            push_down(v);
            if (p < v->lx) {
                v->l = dfs(dfs, v->l);
            } else if (v->rx <= p) {
                v->r = dfs(dfs, v->r);
            } else {
                auto [a, c] = split(v, p, p + 1);
                if (a) v->l = insert_rightmost(v->l, a);
                if (c) v->r = insert_leftmost(v->r, c);
                v->val = v->sum = x;
            }
            update(v);
            return balance(v);
        };
        root = dfs(dfs, root);
    }

    S get(Idx p) {
        node *v = root;
        while (v) {
            push_down(v);
            if (p < v->lx) {
                v = v->l;
            } else if (v->rx <= p) {
                v = v->r;
            } else {
                return v->val;
            }
        }
    }

    void apply(Idx l, Idx r, F lz) {
        auto dfs = [&](auto &&dfs, node *v) -> node* {
            if (!v || r <= v->Lx || v->Rx <= l) return v;
            if (l <= v->Lx && v->Rx <= r) {
                all_apply(v, lz);
                return v;
            }
            push_down(v);
            v->l = dfs(dfs, v->l);
            v->r = dfs(dfs, v->r);
            Idx L = std::max(l, v->lx), R = std::min(r, v->rx);
            if (L < R) {
                if (L != v->lx || R != v->rx) {
                    auto [a, c] = split(v, l, r);
                    if (a) v->l = insert_rightmost(v->l, a);
                    if (c) v->r = insert_leftmost(v->r, c);
                }
                v->val = mapping(lz, v->val, 1);
                v->sum = mapping(lz, v->sum, v->rx - v->lx);
            }
            update(v);
            return balance(v);
        };
        root = dfs(dfs, root);
    }

    S all_prod() {
        return (root ? root->sum_subtree : e());
    }

    S prod(Idx l, Idx r) {
        auto dfs = [&](auto &&dfs, node *v) -> S {
            if (!v || r <= v->Lx || v->Rx <= l) return e();
            if (l <= v->Lx && v->Rx <= r) return v->sum_subtree;
            push_down(v);
            S mid = e();
            Idx L = std::max(l, v->lx), R = std::min(r, v->rx);
            if (L < R) {
                if (l <= v->lx && v->rx <= r) mid = v->sum;
                else mid = pow_monoid(v->val, R - L);
            }
            return op(dfs(dfs, v->l), op(mid, dfs(dfs, v->r)));
        };
        return dfs(dfs, root);
    }

    template<typename G>
    Idx max_right(Idx l, G g) {
        assert(g(e()));
        S lsum = e();
        auto dfs = [&](auto &&dfs, node *v) -> void {
            if (!v) return;
            if (v->Lx == l && g(op(lsum, v->sum_subtree))) {
                l = v->Rx;
                lsum = op(lsum, v->sum_subtree);
                return;
            }
            push_down(v);
            if (v->rx <= l) {
                dfs(dfs, v->r);
                return;
            }
            if (l < v->lx) dfs(dfs, v->l);
            if (l < v->lx) return;
            S x = (v->lx == l ? v->sum : pow_monoid(v->val, v->rx - l));
            if (g(op(lsum, x))) {
                l = v->rx;
                lsum = op(lsum, x);
            } else {
                Idx len = 1;
                std::vector<S> p2{v->val};
                while (len < v->rx - l) {
                    S s = p2.back();
                    p2.push_back(op(s, s));
                    len *= 2;
                }
                for (int i = (int)p2.size() - 1; i >= 0; i--) {
                    len = Idx(1) << i;
                    if ((v->rx - l) >= len && g(op(lsum, p2[i]))) {
                        l += len;
                        lsum = op(lsum, p2[i]);
                    }
                }
                return;
            }
            dfs(dfs, v->r);
        };
        return dfs(dfs, root);
    }

    template<typename G>
    Idx min_left(Idx r, G g) {
        assert(g(e()));
        S rsum = e();
        auto dfs = [&](auto &&dfs, node *v) -> void {
            if (!v) return;
            if (v->Rx == r && g(op(v->sum_subtree, rsum))) {
                r = v->Lx;
                rsum = op(v->sum_subtree, rsum);
                return;
            }
            push_down(v);
            if (v->lx >= r) {
                dfs(dfs, v->l);
                return;
            }
            if (r > v->rx) dfs(dfs, v->r);
            if (r > v->rx) return;
            S x = (v->rx == r ? v->sum : pow_monoid(v->val, r - v->lx));

            if (g(op(x, rsum))) {
                r = v->lx;
                rsum = op(x, rsum);
            } else {
                Idx len = 1;
                std::vector<S> p2{v->val};
                while (len < r - v->lx) {
                    S s = p2.back();
                    p2.push_back(op(s, s));
                    len *= 2;
                }
                for (int i = (int)p2.size() - 1; i >= 0; i--) {
                    len = Idx(1) << i;
                    if ((r - v->lx) >= len && op(p2[i], rsum)) {
                        r -= len;
                        rsum = op(p2[i], rsum);
                    }
                }
                return;
            }
            dfs(dfs, v->l);
        };
        return dfs(dfs, root);
    }
};




#include <type_traits>
#include <iostream>








// @param m `1 <= m`
constexpr long long safe_mod(long long x, long long m){
  x %= m;
  if (x < 0) x += m;
  return x;
}

// x^n mod m
// @param n `0 <= n`
// @param m `1 <= m`
constexpr long long pow_mod_constexpr(long long x, long long n, int m) {
    if (m == 1) return 0;
    unsigned int _m = (unsigned int)(m);
    unsigned long long r = 1;
    unsigned long long y = safe_mod(x, m);
    while (n) {
        if (n & 1) r = (r * y) % _m;
        y = (y * y) % _m;
        n >>= 1;
    }
    return r;
}

constexpr __uint128_t pow_mod64_constexpr(__int128_t x, __uint128_t n, unsigned long long m) {
    if (m == 1) return 0;
    __uint128_t r = 1;
    if (x >= m) x %= m;
    if (x < 0) x += m;
    while (n) {
        if (n & 1) r = (r * x) % m;
        x = (x * x) % m;
        n >>= 1;
    }
    return r;
}



constexpr bool miller_rabin32_constexpr(int n) {
    if (n <= 1) return false;
    if (n == 2 || n == 7 || n == 61) return true;
    if (n % 2 == 0) return false;
    long long d = n - 1;
    while (d % 2 == 0) d /= 2;
    constexpr long long bases[3] = {2, 7, 61};
    for (long long a : bases) {
        long long t = d;
        long long y = pow_mod_constexpr(a, t, n);
        while (t != n - 1 && y != 1 && y != n - 1) { 
            y = y * y % n;
            t <<= 1;
        }
        if (y != n - 1 && t % 2 == 0) {
            return false;
        }
    }
    return true;
}

template<int n>
constexpr bool miller_rabin32 = miller_rabin32_constexpr(n);



#include <cmath>
#include <tuple>

// -10^18 <= _a, _b <= 10^18
long long gcd(long long _a, long long _b) {
    long long a = abs(_a), b = abs(_b);
    if (a == 0) return b;
    if (b == 0) return a;
    int shift = __builtin_ctzll(a | b);
    a >>= __builtin_ctzll(a);
    do{
        b >>= __builtin_ctzll(b);
        if(a > b) std::swap(a, b);
        b -= a;
    } while (b);
    return a << shift;
}

// 最大でa*b
// -10^18 <= a, b <= 10^18
// a, bは負でもいいが非負の値を返す
__int128_t lcm(long long a, long long b) {
    a = abs(a), b = abs(b);
    long long g = gcd(a, b);
    if (!g) return 0;
    return __int128_t(a) * b / g;
}

// {x, y, gcd(a, b)} s.t. ax + by = gcd(a, b)
// g >= 0
std::tuple<long long, long long, long long> extgcd(long long a, long long b) {
    long long x, y;
    for (long long u = y = 1, v = x = 0; a;) {
        long long q = b / a;
        std::swap(x -= q * u, u);
        std::swap(y -= q * v, v);
        std::swap(b -= q * a, a);
    }
    // x + k * (b / g), y - k * (a / g) も条件を満たす(kは任意の整数)
    return {x, y, b};
}

// @param b `1 <= b`
// @return pair(g, x) s.t. g = gcd(a, b), xa = g (mod b), 0 <= x < b/g
constexpr std::pair<long long, long long> inv_gcd(long long a, long long b) {
    a = safe_mod(a, b);
    if (a == 0) return {b, 0};
    long long s = b, t = a;
    long long m0 = 0, m1 = 1;
    while (t) {
        long long u = s / t;
        s -= t * u;
        m0 -= m1 * u;
        auto tmp = s;
        s = t;
        t = tmp;
        tmp = m0;
        m0 = m1;
        m1 = tmp;
    }
    if (m0 < 0) m0 += b / s;
    return {s, m0};
}



template <int m, std::enable_if_t<(1 <= m)>* = nullptr>
struct modint32_static {
    using mint = modint32_static;
  public:
    static constexpr int mod() { return m; }
    
    static mint raw(int v) {
        mint x;
        x._v = v;
        return x;
    }
  
    modint32_static(): _v(0) {}
    
    template <class T>
    modint32_static(T v) { 
        long long x = v % (long long)umod();
        if (x < 0) x += umod();
        _v = x;
    }

    unsigned int val() const { return _v; }
    
    mint& operator ++ () {
        _v++;
        if (_v == umod()) _v = 0;
        return *this;
    }
    mint& operator -- () {
        if (_v == 0) _v = umod();
        _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 >= umod()) _v -= umod();
        return *this;
    }
    mint& operator -= (const mint& rhs) {
        _v -= rhs._v;
        if (_v >= umod()) _v += umod();
        return *this;
    }
    mint& operator *= (const mint& rhs) {
        unsigned long long z = _v;
        z *= rhs._v;
        _v = (unsigned int)(z % umod());
        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 {
        if (prime) {
            assert(_v);
            return pow(umod() - 2);
        } else {
            auto eg = inv_gcd(_v, m);
            assert(eg.first == 1);
            return eg.second;
        }
    }
    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; }
  private:
    unsigned int _v;
    static constexpr unsigned int umod() { return m; }
    static constexpr bool prime = miller_rabin32<m>;
};

template<int m>
std::ostream &operator<<(std::ostream &dest, const modint32_static<m> &a) {
    dest << a.val();
    return dest;
}

using modint998244353 = modint32_static<998244353>;
using modint1000000007 = modint32_static<1000000007>;



using mint = modint998244353;

using S = mint;
using F = std::pair<int, mint>;
using Idx = int;

S op(S x, S y) {
    return x + y;
}
S e() {
    return 0;
}

S mapping(F x, S y, Idx len) {
    if (x.first != -1) y = (mint)x.first * len;
    return y + x.second * len;
}

F composition(F x, F y) {
    if (x.first != -1) return x;
    return {y.first, y.second + x.second};
}

F id() {
    return {-1, mint(0)};
}

int main() {
    std::cin.tie(nullptr);
    std::ios::sync_with_stdio(false);
    int N;
    std::cin >> N;
    std::vector<int> A(N);
    for (int i = 0; i < N; i++) {
        std::cin >> A[i];
    }
    Idx inf = 1000000009;
    segtree_lazy_sparse<Idx, S, op, e, F, mapping, composition, id> seg(0, inf);
    for (int i = 0; i < N; i++) {
        mint sum = (!i ? mint(1) : seg.all_prod());
        sum *= -1;
        seg.apply(A[i] + 1, inf, {0, 0});
        seg.apply(1, A[i] + 1, {-1, sum});
    }
    mint ans = seg.all_prod();
    if (N & 1) ans = -ans;
    std::cout << ans.val() << '\n';
}

Submission Info

Submission Time
Task E - LEQ and NEQ
User tonegawa
Language C++ 23 (gcc 12.2)
Score 700
Code Size 16620 Byte
Status AC
Exec Time 1108 ms
Memory 44044 KiB

Judge Result

Set Name Sample All
Score / Max Score 0 / 0 700 / 700
Status
AC × 2
AC × 34
Set Name Test Cases
Sample sample00, sample01
All case02, case03, case04, case05, case06, case07, case08, case09, case10, case11, case12, case13, case14, case15, case16, case17, case18, case19, case20, case21, case22, case23, case24, case25, case26, case27, case28, case29, case30, case31, case32, case33, sample00, sample01
Case Name Status Exec Time Memory
case02 AC 1108 ms 44032 KiB
case03 AC 2 ms 3660 KiB
case04 AC 1 ms 3520 KiB
case05 AC 1 ms 3512 KiB
case06 AC 45 ms 6104 KiB
case07 AC 4 ms 3688 KiB
case08 AC 1 ms 3432 KiB
case09 AC 1072 ms 44008 KiB
case10 AC 1 ms 3580 KiB
case11 AC 1 ms 3572 KiB
case12 AC 1 ms 3436 KiB
case13 AC 1 ms 3520 KiB
case14 AC 1 ms 3452 KiB
case15 AC 708 ms 43884 KiB
case16 AC 688 ms 43884 KiB
case17 AC 669 ms 43920 KiB
case18 AC 680 ms 43912 KiB
case19 AC 570 ms 43916 KiB
case20 AC 536 ms 43952 KiB
case21 AC 525 ms 44044 KiB
case22 AC 529 ms 43888 KiB
case23 AC 1009 ms 43924 KiB
case24 AC 1030 ms 43924 KiB
case25 AC 1025 ms 43916 KiB
case26 AC 34 ms 5168 KiB
case27 AC 46 ms 4816 KiB
case28 AC 720 ms 43916 KiB
case29 AC 718 ms 43920 KiB
case30 AC 746 ms 43884 KiB
case31 AC 623 ms 44032 KiB
case32 AC 635 ms 43964 KiB
case33 AC 618 ms 43976 KiB
sample00 AC 1 ms 3496 KiB
sample01 AC 1 ms 3500 KiB