module Main; // import BinaryHeap; // import BoolArray; // import CPLib.Arithmetic; // import CPLib.Bipartite; // import CPLib.Bits; // import CPLib.Convolution; // import CPLib.DSegtree; // import CPLib.Graph; import CPLib.IO; // import CPLib.LDSegtree; // import CPLib.LSegtree; // import CPLib.MaxFlow; // import CPLib.Memoize; // import CPLib.MinCostFlow; // import CPLib.Misc; import CPLib.Monoid; import CPLib.Segtree; // import CPLib.String; // import CPLib.Trait; // import CPLib.TwoSat; // import CPLib.UnionFind; import CPLib.ZP; // import HashMap; // import HashSet; type Z = ZP P998244353; main : IO () = ( let iN = *read_i; let iAs = *read_is(iN); let sorted = iAs.to_iter.enumerate.to_array.sort_by(|(a, b)| a.@1 < b.@1); // xs[i] = sum { A(i) + A(j) | A(i) > A(j), i < j } let tree_a = Segtree::create(iN) : Segtree (Sum Z); let tree_c = Segtree::create(iN) : Segtree (Sum I64); let xs = fill(iN, zp(0) : Z); let xs = loop((0, tree_a, tree_c, xs), |(i, tree_a, tree_c, xs)| if i >= iN { xs.break }; let j = loop(i+1, |j| if j >= iN { iN.break } else if sorted.@(j).@1 > sorted.@(i).@1 { j.break } else { (j+1).continue }); // eval "i = {}, j = {}".debug_eprintfln((i, j,)); let xs = range(i, j).fold(xs, |i, xs| let (idx, a) = sorted.@(i); let sum = tree_a.fold(idx+1, iN).@v; // eval "idx+1 = {}, iN = {}, sum = {}".debug_eprintfln((idx+1, iN, sum.@value,)); let cnt = tree_c.fold(idx+1, iN).@v; let v = sum + zp(cnt) * zp(a); let xs = xs[idx].iset(v); xs ); let (tree_a, tree_c) = range(i, j).fold((tree_a, tree_c), |i, (tree_a, tree_c)| let (idx, a) = sorted.@(i); // eval "tree_a set idx = {}, a = {}".debug_eprintfln((idx, a,)); let tree_a = tree_a.set(idx, Sum { v: zp(a) }); let tree_c = tree_c.set(idx, Sum { v: 1 }); (tree_a, tree_c) ); let i = j; (i, tree_a, tree_c, xs).continue ); let ys = xs; // eval "ys = {}".debug_eprintfln((ys.map(@value),)); let tree_a = Segtree::create(iN) : Segtree (Sum Z); let tree_c = Segtree::create(iN) : Segtree (Sum I64); let tree_d = Segtree::create(iN) : Segtree (Sum I64); let xs = fill(iN, zp(0) : Z); let xs = loop((0, tree_a, tree_c, tree_d, xs), |(i, tree_a, tree_c, tree_d, xs)| if i >= iN { xs.break }; let j = loop(i+1, |j| if j >= iN { iN.break } else if sorted.@(j).@1 > sorted.@(i).@1 { j.break } else { (j+1).continue }); let xs = range(i, j).fold(xs, |i, xs| let (idx, a) = sorted.@(i); let sum = tree_a.fold(idx+1, iN).@v; let cnt = tree_d.fold(idx+1, iN).@v; // eval "idx = {}, sum = {}, cnt = {}".debug_eprintfln((idx, sum.@value, cnt,)); let v = sum + zp(cnt) * zp(a); let xs = xs[idx].iset(v); xs ); let tree_d = range(i, j).fold(tree_d, |i, tree_d| let (idx, a) = sorted.@(i); let cnt = tree_c.fold(idx+1, iN).@v; let tree_d = tree_d.set(idx, Sum { v: cnt }); tree_d ); let (tree_a, tree_c) = range(i, j).fold((tree_a, tree_c), |i, (tree_a, tree_c)| let (idx, a) = sorted.@(i); let tree_a = tree_a.set(idx, Sum { v: ys.@(idx) }); let tree_c = tree_c.set(idx, Sum { v: 1 }); (tree_a, tree_c) ); let i = j; (i, tree_a, tree_c, tree_d, xs).continue ); let ans = xs.to_iter.sum; ans.@value.to_string.println;; pure() );