#include #define rep(i,m) for(long long i=0; i=0; i--) #define FOR(i,n,m) for(long long i=n; i=n; i--) #define SORT(v,n) do{sort(v,v+n);reverse(v,v+n);}while(0) #define all(x) (x).begin(),(x).end() #define F first #define S second #define MP make_pair #define MT make_tuple #define PB push_back #define PQ priority_queue #define EPS (1e-7) #define PI (acos(-1)) #define dump(x) cerr << #x << " = " << (x) << endl; #define debug(x) cerr << #x << " = " << (x) << " (L" << __LINE__ << ")" << " " << __FILE__ << endl; using namespace std; typedef long long ll; const ll INF = 1000000000000000000; const ll MOD = 998244353; typedef pair P; typedef pair LP; std::ostream &operator<<(std::ostream &dest, __int128_t value) { std::ostream::sentry s(dest); if (s) { __uint128_t tmp = value < 0 ? -value : value; char buffer[128]; char *d = std::end(buffer); do { --d; *d = "0123456789"[tmp % 10]; tmp /= 10; } while (tmp != 0); if (value < 0) { --d; *d = '-'; } int len = std::end(buffer) - d; if (dest.rdbuf()->sputn(d, len) != len) { dest.setstate(std::ios_base::badbit); } } return dest; } ll POW(ll x,ll n){ x%=MOD; if(n==0)return 1; if(n%2==0)return POW(x*x,n/2)%MOD; return x%MOD*POW(x,n-1)%MOD; } ll POW2(ll x,ll n){ if(n==0)return 1; if(n%2==0)return POW2(x*x,n/2); return x*POW2(x,n-1); } ll POW3(ll x,ll n,ll m){ x%=m; if(n==0)return 1; if(n%2==0)return POW3(x*x,n/2,m)%m; return x*POW3(x,n-1,m)%m; } ll gcd(ll u, ll v) { ll r; while (0 != v) { r = u % v; u = v; v = r; } return u; } ll lcm(ll u, ll v) { return u/gcd(u,v)*v; } ll kaikai[510000]={}; ll KAI(ll m) { if(kaikai[m])return kaikai[m]; if(m<0) return 0; if(m==0) return 1; kaikai[m]=m*KAI(m-1)%MOD; return kaikai[m]; } ll KAI2(ll m) { if(m<0) return 0; if(m==0) return 1; return m*KAI2(m-1); } ll extGCD(ll a, ll b, ll &x, ll &y) { if (b == 0) { x = 1; y = 0; return a; } ll d = extGCD(b, a%b, y, x); y -= a / b * x; return d; } inline ll mod(ll a, ll m) { return (a % m + m) % m; } ll modinv(ll a) { ll x, y; extGCD(a, MOD, x, y); return mod(x, MOD); } /* ll COM(ll m,ll n) { if(m1){ mid=(ok+ng)/2; if(mid*mid<=n){ ok=mid; } else{ ng=mid; } } return ok; } struct UnionFind { vector par; vector sizes; UnionFind(int n) : par(n), sizes(n, 1) { rep(i,n) par[i] = i; } int find(int x) { if (x == par[x]) return x; return par[x] = find(par[x]); } void unite(int x, int y) { x = find(x); y = find(y); if (x == y) return; if (sizes[x] < sizes[y]) swap(x, y); par[y] = x; sizes[x] += sizes[y]; } bool same(int x, int y) { return find(x) == find(y); } int size(int x) { return sizes[find(x)]; } }; map< int64_t, int > prime_factor(int64_t n) { map< int64_t, int > ret; for(int64_t i = 2; i * i <= n; i++) { while(n % i == 0) { ret[i]++; n /= i; } } if(n != 1) ret[n] = 1; return ret; } bool is_prime(int64_t x) { if(x==1)return false; for(int64_t i = 2; i * i <= x; i++) { if(x % i == 0) return false; } return true; } struct edge{ll to, cost;}; struct Dij{ ll V; vector > G; vector d; Dij(ll n){ init(n); } void init(ll n){ V = n; G.resize(V); d.resize(V); rep(i,V){ d[i] = INF; } } void add(ll s, ll t, ll cost){ edge e; e.to = t, e.cost = cost; G[s].push_back(e); } void find(ll s){ rep(i,V){ d[i] = INF; } d[s] = 0; priority_queue, greater > que; que.push(LP(0,s)); while(!que.empty()){ LP p = que.top(); que.pop(); ll v = p.second; if(d[v]d[v]+e.cost){ d[e.to] = d[v]+e.cost; que.push(LP(d[e.to],e.to)); } } } } }; struct BF{ ll V; vector> G; vector d; BF(ll n){ init(n); } void init(ll n){ V = n; G.resize(V); d.resize(V); rep(i,V){ d[i]=INF; } } void add(ll s, ll t, ll cost){ edge e; e.to=t,e.cost=cost; G[s].push_back(e); } bool find(ll s){ rep(i,V){ d[i]=INF; } d[s]=0; rep(i,V){ rep(j,V){ ll m=G[j].size(); rep(k,m){ edge e=G[j][k]; if(d[j]!=INF&&d[e.to]>d[j]+e.cost){ d[e.to]=d[j]+e.cost; if(i==V-1)return true; } } } } return false; } bool find2(ll s,ll t){ rep(i,V){ d[i]=INF; } d[s]=0; rep(i,V*2){ rep(j,V){ ll m=G[j].size(); rep(k,m){ edge e=G[j][k]; if(d[j]!=INF&&d[e.to]>d[j]+e.cost){ if(i>=V-1&&e.to==t)return true; else if(i>=V-1)d[e.to]=-INF; else d[e.to]=d[j]+e.cost; } } } } return false; } }; ll dist[400][400]; void WF(ll n){ rep(i,n)rep(j,n)rep(k,n)dist[j][k]=min(dist[j][k],dist[j][i]+dist[i][k]); } struct bit{ ll m; vector b; bit(ll i){ m=i; b.resize(m+1); } ll num(ll i){ return b[i]; } ll sum(ll i){ ll s=0; while(i>0){ s+=b[i]; i-=i&-i; } return s; } void add(ll i, ll x){ while(i<=m){ b[i]+=x; i+=i&-i; } } }; struct Segtree{ ll N=1; ll elem; vector value; ll calc(ll s,ll t){ return (s+t)%MOD; //演算 } Segtree(ll n,ll Elem){ elem=Elem; while(N0){ i=(i-1)/2; value[i]=calc(value[i*2+1],value[i*2+2]); } } ll query(ll a,ll b,ll k,ll l,ll r){ if(r<=a||b<=l)return elem; if(a<=l&&r<=b)return value[k]; else{ ll c1=query(a,b,2*k+1,l,(l+r)/2); ll c2=query(a,b,2*k+2,(l+r)/2,r); return calc(c1,c2); } } ll find(ll s,ll t){ return query(s,t+1,0,0,N); } ll v(ll s){ return query(s,s+1,0,0,N); } }; string LCS(string s,string t){ ll x=s.size(); ll dp[x+1][x+1]={},m[x+1][x+1]={},a,b; string h; stackp; a=s.size(); b=t.size(); rep(i,a){ rep(j,b){ if(s[i]==t[j]){ dp[i+1][j+1]=dp[i][j]+1; m[i+1][j+1]=0; } dp[i+1][j+1]=max({dp[i+1][j],dp[i][j+1],dp[i+1][j+1]}); if(dp[i+1][j+1]==dp[i+1][j]){ m[i+1][j+1]=1; } if(dp[i+1][j+1]==dp[i][j+1]){ m[i+1][j+1]=2; } } } while(a>=1&&b>=1){ if(m[a][b]==0){ p.push(s[a-1]); a--; b--; } else if(m[a][b]==1)b--; else a--; } while(p.size()){ h+=p.top(); p.pop(); } return h; } struct Edge{ ll src, dst; ll cap; Edge(ll src_, ll dst_, ll cap_) : src(src_), dst(dst_), cap(cap_) { } }; struct EK{ ll n; vector prev, dist; vector> cap, flow; vector> g; ll inf; EK(ll n) : n(n), cap(n, vector(n)), flow(n, vector(n)), g(n, vector()), inf(INF){} EK(const vector> &graph){ *this = EK(graph.size()); rep(i,n) for(auto &e : graph[i]) add(e.src, e.dst, e.cap); } void add(ll u, ll v, ll c){ cap[u][v] += c; cap[v][u] += c; flow[v][u] += c; g[u].push_back(v); g[v].push_back(u); } ll find(ll s, ll t){ ll res = 0, aug = 1; while(aug > 0){ prev.assign(n, -1); dist.assign(n, inf); dist[s] = 0; res += (aug = augment(s,t)); } return res; } ll augment(ll s, ll t){ queue> q; q.emplace(s,inf); ll aug = 0; while(q.size()){ ll v; ll f; tie(v,f) = q.front(); q.pop(); if(v == t){ aug = f; break; } for(const ll& d : g[v]){ if(dist[d] <= dist[v] + 1 || cap[v][d] - flow[v][d] == 0) continue; dist[d] = dist[v] + 1; prev[d] = v; q.emplace(d, min(f, cap[v][d] - flow[v][d])); } } if(aug == 0) return 0; ll c = t; while(c != s){ ll p = prev[c]; flow[p][c] += aug; flow[c][p] -= aug; c = p; } return aug; } }; ll LIS(vectora) { ll n=a.size(); ll dp[n]; fill(dp,dp+n,INF); rep(i,n)*lower_bound(dp,dp+n,a[i])=a[i]; return lower_bound(dp,dp+n,INF)-dp; } struct RMQ{ ll N=1; ll elem=INF; vector value; RMQ(ll n){ while(N>v; vectorvs; vectorid; vectordepth; vectorr; ll k; ll N; LCA(ll n){ v.resize(n); id.resize(n); r.PB((RMQ){2*n-1}); N=n; } void add(ll s,ll t){ v[s].PB(t); } void root(ll n){ k=0; dfs(n,0); r[0].UPDATE(); } void dfs(ll n,ll d){ id[n]=k; ll m=v[n].size(); rep(i,m){ vs.PB(n); depth.PB(d); r[0].update(k,d); k++; dfs(v[n][i],d+1); } vs.PB(n); depth.PB(d); r[0].update(k,d); k++; } ll find(ll s,ll t){ return vs[r[0].find(min(id[s],id[t]),max(id[s],id[t]))]; } ll dist(ll s,ll t){ return depth[id[s]]+depth[id[t]]-2*depth[r[0].find(min(id[s],id[t]),max(id[s],id[t]))]; } }; int main(){ ll n,a[210000],ans=0,x[210000],y[210000],z[210000],w[210000]; cin >> n; rep(i,n)cin >> a[i]; vectorv; rep(i,n)v.PB(MP(a[i],i)); sort(all(v)); Segtree s(n,0); Segtree s2(n,0); rep(i,n){ s.update(v[i].S,v[i].F); s2.update(v[i].S,1); x[v[i].S]=s2.find(v[i].S+1,n-1); y[v[i].S]=s.find(v[i].S+1,n-1); } reverse(all(v)); rep(i,n)s.update(i,0); rep(i,n)s2.update(i,0); rep(i,n){ s.update(v[i].S,v[i].F); s2.update(v[i].S,1); if(v[i].S)z[v[i].S]=s2.find(0,v[i].S-1); if(v[i].S)w[v[i].S]=s.find(0,v[i].S-1); } rep(i,n){ ans+=x[i]*z[i]%MOD*a[i]%MOD; ans%=MOD; ans+=y[i]*z[i]%MOD; ans%=MOD; ans+=x[i]*w[i]%MOD; ans%=MOD; } printf("%lld",mod(ans,MOD)); }