/** * code generated by JHelper * More info: https://github.com/AlexeyDmitriev/JHelper * @author Gosu_Hiroo */ #include using namespace std; using ll = long long; template using P = pair; //#pragma GCC optimize("O3") //#pragma GCC target("avx2") //#pragma GCC target("avx512f") //#pragma GCC optimize("unroll-loops") //#pragma GCC target("sse,sse2,sse3,ssse3,sse4,popcnt,abm,mmx,avx,tune=native") //#pragma GCC optimize("Ofast") #define V vector #define G(size_1) vector>(size_1, vector()) #define SZ(x) ((long long)(x).size()) #define READ ({long long t;cin >> t;t;}) #define FOR(i, __begin, __end) for (auto i = (__begin) - ((__begin) > (__end)); i != (__end) - ((__begin) > (__end)); i += 1 - 2 * ((__begin) > (__end))) #define REP(i, __end) for (auto i = decltype(__end){0}; i < (__end); ++i) #define ALL(x) (x).begin(),(x).end() #define RALL(x) (x).rbegin(),(x).rend() #define F first #define S second #define y0 y3487465 #define y1 y8687969 #define j0 j1347829 #define j1 j234892 #define BIT(n) (1LL<<(n)) #define UNIQUE(v) v.erase( unique(v.begin(), v.end()), v.end() ); #define EB emplace_back #define PB push_back #define fcout cout << fixed << setprecision(12) #define fcerr cerr << fixed << setprecision(12) #define print(x) cout << (x) << '\n' #define printE(x) cout << (x) << '\n'; #define fprint(x) cout << fixed << setprecision(12) << (x) << '\n'; # define BYE(a) do { cout << (a) << endl; return ; } while (false) #define LB lower_bound #define UB upper_bound #define LBI(c, x) distance((c).begin(), lower_bound((c).begin(), (c).end(), (x))) #define UBI(c, x) distance((c).begin(), upper_bound((c).begin(), (c).end(), (x))) #ifdef DEBUG #define DBG(args...) { string _s = #args; replace(_s.begin(), _s.end(), ',', ' '); stringstream _ss(_s); istream_iterator _it(_ss); _err(cerr,_it, args); } #define ERR(args...) { string _s = #args; replace(_s.begin(), _s.end(), ',', ' '); stringstream _ss(_s); istream_iterator _it(_ss); _err(std::cerr,_it, args); } #else #define DBG(args...) {}; #define ERR(args...) {}; #endif void _err(std::ostream& cerr, istream_iterator it){cerr << endl;} template void _err(std::ostream& cerr, istream_iterator it, T a, Args... args){ cerr << *it << " = " << a << " "; _err(cerr, ++it, args...); } namespace aux{ template struct seq{ }; template struct gen_seq : gen_seq{ }; template struct gen_seq<0, Is...> : seq{ }; template void print_tuple(std::basic_ostream& os, Tuple const& t, seq){ using swallow = int[]; (void) swallow{0, (void(os << (Is == 0 ? "" : ",") << std::get(t)), 0)...}; } template void read_tuple(std::basic_istream& os, Tuple& t, seq){ using swallow = int[]; (void) swallow{0, (void(os >> std::get(t)), 0)...}; } } // aux:: template auto operator<<(std::basic_ostream& os, std::tuple const& t) -> std::basic_ostream&{ os << "("; aux::print_tuple(os, t, aux::gen_seq()); return os << ")"; } template auto operator>>(std::basic_istream& os, std::tuple& t) -> std::basic_istream&{ aux::read_tuple(os, t, aux::gen_seq()); return os; } template inline bool chmax(T& a, const T& b){ if(a < b){ a = b; return 1; } return 0; } template inline bool chmin(T& a, const T& b){ if(b < a){ a = b; return 1; } return 0; } template istream& operator>>(istream& is, pair& V){ is >> V.F >> V.S; return is; } template istream& operator>>(istream& is, vector & V){ for(auto&& ele : V)is >> ele; return is; } template ostream& operator<<(ostream& os, const vector V){ os << "["; int cnt = 0; T curr; if(!V.empty()){ for(int i = 0; i < V.size() - 1; ++i){ if(V[i] == curr)cnt++; else cnt = 0; if(cnt == 4)os << "... "; if(cnt < 4) os << i << ":" << V[i] << " "; curr = V[i]; } os << V.size() - 1 << ":" << V.back(); } os << "]\n"; return os; } template ostream& operator<<(ostream& os, const pair P){ os << "("; os << P.first << "," << P.second; os << ")"; return os; } template ostream& operator<<(ostream& os, const set V){ os << "{"; if(!V.empty()){ auto it = V.begin(); for(int i = 0; i < V.size() - 1; ++i){ os << *it << " "; it++; } os << *it; } os << "}\n"; return os; } template ostream& operator<<(ostream& os, const unordered_set V){ os << "{"; if(!V.empty()){ auto it = V.begin(); for(int i = 0; i < V.size() - 1; ++i){ os << *it << " "; it++; } os << *it; } os << "}\n"; return os; } template ostream& operator<<(ostream& os, const multiset V){ os << "{"; if(!V.empty()){ auto it = V.begin(); for(int i = 0; i < V.size() - 1; ++i){ os << *it << " "; it++; } os << *it; } os << "}"; return os; } template ostream& operator<<(ostream& os, const map V){ os << "{"; if(!V.empty()){ auto it = V.begin(); for(int i = 0; i < V.size() - 1; ++i){ os << "("; os << it->first << "," << it->second; os << ") "; it++; } os << "("; os << it->first << "," << it->second; os << ")"; } os << "}\n"; return os; } template ostream& operator<<(ostream& os, const unordered_map V){ os << "{"; if(!V.empty()){ auto it = V.begin(); for(int i = 0; i < V.size() - 1; ++i){ os << "("; os << it->first << "," << it->second; os << ") "; it++; } os << "("; os << it->first << "," << it->second; os << ")"; } os << "}\n"; return os; } template ostream& operator<<(ostream& os, const deque V){ os << "["; if(!V.empty()){ for(int i = 0; i < V.size() - 1; ++i){ os << V[i] << "->"; } if(!V.empty())os << V.back(); } os << "]\n"; return os; }; template ostream& operator<<(ostream& os, const priority_queue V){ priority_queue _V = V; os << "["; if(!_V.empty()){ while(_V.size() > 1){ os << _V.top() << "->"; _V.pop(); } os << _V.top(); } os << "]\n"; return os; }; template struct y_combinator{ F f; // the lambda will be stored here // a forwarding operator(): template decltype(auto) operator()(Args&& ... args) const{ // we pass ourselves to f, then the arguments. // the lambda should take the first argument as `auto&& recurse` or similar. return f(*this, std::forward(args)...); } }; // helper function that deduces the type of the lambda: template y_combinator> recursive(F&& f){ return {std::forward(f)}; } struct hash_pair{ template size_t operator()(const pair& p) const{ auto hash1 = hash{}(p.first); auto hash2 = hash{}(p.second); return hash1^hash2; } }; template auto vec(int n, U v){ return std::vector(n, v); } template auto vec(int n, Args... args){ auto val = vec(std::forward(args)...); return std::vector(n, std::move(val)); } const double PI = 2*acos(.0); const int INF = 0x3f3f3f3f; template inline T ceil(T a, T b){return (a + b - 1)/b;} inline long long popcount(ll x){return __builtin_popcountll(x);} class No1300SumOfInversions{ public: void solve(std::istream&, std::ostream&, std::ostream&); }; template struct Compress{ vector xs; Compress() = default; Compress(const vector& vs){ add(vs); } Compress(const initializer_list >& vs){ for(auto& p : vs) add(p); } void add(const vector& vs){ copy(begin(vs), end(vs), back_inserter(xs)); } void add(const T& x){ xs.emplace_back(x); } void build(){ sort(begin(xs), end(xs)); xs.erase(unique(begin(xs), end(xs)), end(xs)); } vector get(const vector& vs) const{ vector ret; transform(begin(vs), end(vs), back_inserter(ret), [&](const T& x){ return lower_bound(begin(xs), end(xs), x) - begin(xs); }); return ret; } int get(const T& x) const{ return lower_bound(begin(xs), end(xs), x) - begin(xs); } const T& operator[](int k) const{ return xs[k]; } }; template struct mod_int{ constexpr static signed MODULO = M; constexpr static unsigned TABLE_SIZE = T; signed x; mod_int() : x(0){} mod_int(long long y) : x(static_cast(y >= 0 ? y%MODULO : MODULO - (-y)%MODULO)){} mod_int(int y) : x(y >= 0 ? y%MODULO : MODULO - (-y)%MODULO){} explicit operator int() const{ return x; } explicit operator long long() const{ return x; } explicit operator double() const{ return x; } mod_int& operator+=(const mod_int& rhs){ if((x += rhs.x) >= MODULO) x -= MODULO; return *this; } mod_int& operator-=(const mod_int& rhs){ if((x += MODULO - rhs.x) >= MODULO) x -= MODULO; return *this; } mod_int& operator*=(const mod_int& rhs){ x = static_cast(1LL*x*rhs.x%MODULO); return *this; } mod_int& operator/=(const mod_int& rhs){ x = static_cast((1LL*x*rhs.inv().x)%MODULO); return *this; } mod_int operator-() const{return mod_int(-x);} mod_int operator+(const mod_int& rhs) const{return mod_int(*this) += rhs;} mod_int operator-(const mod_int& rhs) const{return mod_int(*this) -= rhs;} mod_int operator*(const mod_int& rhs) const{return mod_int(*this) *= rhs;} mod_int operator/(const mod_int& rhs) const{return mod_int(*this) /= rhs;} bool operator<(const mod_int& rhs) const{return x < rhs.x;} mod_int inv() const{ assert(x != 0); if(x <= static_cast(TABLE_SIZE)){ if(_inv[1].x == 0) prepare(); return _inv[x]; }else{ signed a = x, b = MODULO, u = 1, v = 0, t; while(b){ t = a/b; a -= t*b; std::swap(a, b); u -= t*v; std::swap(u, v); } return mod_int(u); } } mod_int pow(long long t) const{ assert(!(x == 0 && t == 0)); mod_int e = *this, res = mod_int(1); for(; t; e *= e, t >>= 1) if(t&1) res *= e; return res; } mod_int fact(){ if(_fact[0].x == 0) prepare(); return _fact[x]; } mod_int inv_fact(){ if(_fact[0].x == 0) prepare(); return _inv_fact[x]; } mod_int choose(mod_int y){ assert(y.x <= x); return this->fact()*y.inv_fact()*mod_int(x - y.x).inv_fact(); } static mod_int _inv[TABLE_SIZE + 1]; static mod_int _fact[TABLE_SIZE + 1]; static mod_int _inv_fact[TABLE_SIZE + 1]; static void prepare(){ _inv[1] = 1; for(int i = 2; i <= (int) TABLE_SIZE; ++i){ _inv[i] = 1LL*_inv[MODULO%i].x*(MODULO - MODULO/i)%MODULO; } _fact[0] = 1; for(unsigned i = 1; i <= TABLE_SIZE; ++i){ _fact[i] = _fact[i - 1]*int(i); } _inv_fact[TABLE_SIZE] = _fact[TABLE_SIZE].inv(); for(int i = (int) TABLE_SIZE - 1; i >= 0; --i){ _inv_fact[i] = _inv_fact[i + 1]*(i + 1); } } }; template std::ostream& operator<<(std::ostream& os, const mod_int& rhs){ return os << rhs.x; } template std::istream& operator>>(std::istream& is, mod_int& rhs){ long long s; is >> s; rhs = mod_int(s); return is; } template mod_int mod_int::_inv[TABLE_SIZE + 1]; template mod_int mod_int::_fact[TABLE_SIZE + 1]; template mod_int mod_int::_inv_fact[TABLE_SIZE + 1]; template bool operator==(const mod_int& lhs, const mod_int& rhs){ return lhs.x == rhs.x; } template bool operator!=(const mod_int& lhs, const mod_int& rhs){ return !(lhs == rhs); } constexpr int MF = 1000010; //constexpr int MOD = 1000000007; constexpr int MOD = 998244353; using mint = mod_int; mint binom(int n, int r){return (r < 0 || r > n || n < 0) ? 0 : mint(n).choose(r);} mint fact(int n){return mint(n).fact();} mint inv_fact(int n){return mint(n).inv_fact();} #ifndef ATCODER_SEGTREE_HPP #define ATCODER_SEGTREE_HPP 1 #include #ifndef ATCODER_INTERNAL_BITOP_HPP #define ATCODER_INTERNAL_BITOP_HPP 1 #ifdef _MSC_VER #include #endif namespace atcoder { namespace internal { // @param n `0 <= n` // @return minimum non-negative `x` s.t. `n <= 2**x` int ceil_pow2(int n) { int x = 0; while ((1U << x) < (unsigned int)(n)) x++; return x; } // @param n `1 <= n` // @return minimum non-negative `x` s.t. `(n & (1 << x)) != 0` int bsf(unsigned int n) { #ifdef _MSC_VER unsigned long index; _BitScanForward(&index, n); return index; #else return __builtin_ctz(n); #endif } } // namespace internal } // namespace atcoder #endif // ATCODER_INTERNAL_BITOP_HPP #include #include namespace atcoder { template struct segtree { public: std::vector d; segtree() : segtree(0) {} segtree(int n) : segtree(std::vector(n, e())) {} segtree(const std::vector& v) : _n(int(v.size())) { log = internal::ceil_pow2(_n); size = 1 << log; d = std::vector(2 * size, e()); for (int i = 0; i < _n; i++) d[size + i] = v[i]; for (int i = size - 1; i >= 1; i--) { update(i); } } void set(int p, S x) { assert(0 <= p && p < _n); p += size; d[p] = x; for (int i = 1; i <= log; i++) update(p >> i); } S get(int p) { assert(0 <= p && p < _n); return d[p + size]; } S prod(int l, int r) { assert(0 <= l && l <= r && r <= _n); S sml = e(), smr = e(); l += size; r += size; 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]; } template int max_right(int l) { return max_right(l, [](S x) { return f(x); }); } template int max_right(int l, F f) { assert(0 <= l && l <= _n); assert(f(e())); if (l == _n) return _n; l += size; S sm = e(); do { while (l % 2 == 0) l >>= 1; if (!f(op(sm, d[l]))) { while (l < size) { l = (2 * l); if (f(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 int min_left(int r) { return min_left(r, [](S x) { return f(x); }); } template int min_left(int r, F f) { assert(0 <= r && r <= _n); assert(f(e())); if (r == 0) return 0; r += size; S sm = e(); do { r--; while (r > 1 && (r % 2)) r >>= 1; if (!f(op(d[r], sm))) { while (r < size) { r = (2 * r + 1); if (f(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; } S operator[](int p){ assert(0 <= p && p < _n); return d[p + size]; } private: int _n, size, log; // std::vector d; void update(int k) { d[k] = op(d[2 * k], d[2 * k + 1]); } }; } // namespace atcoder #endif // ATCODER_SEGTREE_HPP using namespace atcoder; namespace arg{ using S = mint; S op(S s1, S s2){ return s1 + s2; } S unit(){ return 0; } } using st = segtree; void No1300SumOfInversions::solve(std::istream& cin, std::ostream& cout, std::ostream& cerr){ int N; cin >> N; V a(N); cin >> a; Compress compress(a); compress.build(); auto a_i = compress.get(a); st seg(N), seg2(N); st segc(N), segc2(N); V s1(N), s2(N); V c1(N), c2(N); REP(i, N){ s1[i] = seg.prod(a_i[i] + 1, N); seg.set(a_i[i], seg[a_i[i]] + a[i]); c1[i] = segc.prod(a_i[i] + 1, N); segc.set(a_i[i], segc[a_i[i]] + 1); } FOR(i, N, 0){ s2[i] = seg2.prod(0, a_i[i]); seg2.set(a_i[i], seg2[a_i[i]] + a[i]); c2[i] = segc2.prod(0, a_i[i]); segc2.set(a_i[i], segc2[a_i[i]] + 1); } DBG(s1, s2, c1, c2) mint ans = 0; FOR(i, 1, N - 1)ans += c1[i]*(s2[i]) + c2[i]*(s1[i]) + c1[i]*c2[i]*a[i]; print(ans); } #undef int int main() { No1300SumOfInversions solver; std::istream& in(std::cin); std::ostream& out(std::cout); std::ostringstream err; in.tie(0); ios::sync_with_stdio(0); solver.solve(in, out,err); return 0; }