package main import "fmt" import "io/ioutil" import "math" import "math/bits" import "os" import "sort" const P int = 1e9 + 7 func times(before, count, after int) int { result := ((before + count) * (after + count) - count * (count - 1) / 2) % P //Log("times", before, count, after, "=", result) return result } func sumtriangle(n int) int { Assert(-1 <= n && n < 5e5) return n * (n + 1) * (n + 2) / 6 % P } func sumsquare(n int) int { Assert(-1 <= n && n < 5e5) return n * (n + 1) * (2 * n + 1) / 6 % P } func main() { N := ScanInt(1, 2e5) NewLine() A := make([]int, N) for n := range A { A[n] = ScanInt(0, 1e6) // ! } indices := make([]int, N) for n := range indices { indices[n] = n } sort.Slice(indices, func(i, j int) bool { return A[indices[i]] > A[indices[j]] }) var done OrderedNSet done.Init(N) sum := 0 { i0 := indices[0] done.Insert(i0) a0 := A[i0] count := 1 before := i0 times0 := 0 for n := N; n > 0; n-- { after := (n * (n + 1) / 2 - i0 - count) % P times0 = (times0 + times(before % P, count, after % P)) % P before = (n - i0 - count) if i0 > 0 { count++ i0-- before += i0 } if i0 + count >= n { count-- } } //Log(indices[0], a0, times0) sum = (sum + times0 * a0) % P } first := indices[0] last := indices[0] for _, i := range indices[1:] { done.Insert(i) if i < first { first = i } else if i > last { last = i } k := done.Index(i) timesi := 0 before := 0 after := 0 extrab := 0 extraa := 0 if i == first { extrab = N - last before = i } else { prev := done.At(k - 1) before = i - prev - 1 } if i == last { extraa = first if extraa > 0 { extraa-- } after = N - i - 1 } else { next := done.At(k + 1) after = next - i - 1 } count := 1 for n, doing := N, 0; n > 0 && count > 0; n -= doing { if n == N { doing = 1 timesi = (timesi + times(before, count, after + extraa)) % P } else { deltac := 1 deltab := 0 if before > 0 { deltab = 1 } else { deltac-- } if extrab > 0 { deltab++ } deltaa := 0 if after > 0 { deltaa = 1 } else { deltac-- } if extraa > 0 { deltaa++ } doing = count if deltac >= 0 { doing = 0 } for _, x := range [4]int{ before, after, extraa, extrab } { if x > 0 && (doing == 0 || x < doing) { doing = x } } Assert(doing > 0) zd := doing * (doing - 1) / 2 % P db := (P + deltac - deltab) % P da := (P + deltac - deltaa) % P xb := before + extrab + count xa := after + extraa + count z1 := xb * xa % P * doing % P z2 := xb * zd % P * da % P z3 := xa * zd % P * db % P z4 := da * db % P * sumsquare(doing - 1) % P z5 := 0 switch deltac { case -1: Assert(doing <= count) z5 = sumtriangle(count - 1) - sumtriangle(count - 1 - doing) case 0: z5 = count * (count - 1) / 2 % P * doing case 1: z5 = sumtriangle(count + doing - 2) - sumtriangle(count - 2) default: Assert(false) } z5 = (P + z5) % P z5 = (P - z5) % P timesi = (timesi + z1 + z2 + z3 + z4 + z5) % P } if extrab > 0 { Assert(extrab >= doing) extrab -= doing } if extraa > 0 { Assert(extraa >= doing) extraa -= doing } count += doing if before > 0 { Assert(before >= doing) before -= doing } else { count -= doing } if after > 0 { Assert(after >= 0) after -= doing } else { Assert(count >= 0) count -= doing } } //Log(i, A[i], timesi) sum = (sum + timesi * A[i]) % P } fmt.Println(sum) } func Assert(condition bool) { if !condition { panic("assertion failed") } } func Log(items... interface{}) { fmt.Println(items...) } func NewLine() { if CheckInput { for n, b := range RemainingInput { if b != ' ' && b != '\t' && b != '\r' { Assert(b == '\n') RemainingInput = RemainingInput[n+1:] return } } Assert(false) } } // A subset of the integers from [0,N) type OrderedNSet Fenwick func (o *OrderedNSet) Init(N int) { ((*Fenwick)(o)).Init(N) } func (o OrderedNSet) Insert(n int) bool { f := Fenwick(o) if f.At(n) != 0 { return false } f.Add(n, 1) return true } func (o OrderedNSet) Remove(n int) bool { f := Fenwick(o) if f.At(n) == 0 { return false } f.Add(n, -1) return true } func (o OrderedNSet) Contains(n int) bool { f := Fenwick(o) return f.At(n) != 0 } func (o OrderedNSet) Count() int { f := Fenwick(o) return f.SumPrefix(len(o)) } func (o OrderedNSet) At(k int) int { Assert(k >= 0) f := Fenwick(o) n := f.SearchSum(k + 1) Assert(n >= 1) return n - 1 } func (o OrderedNSet) Index(n int) int { f := Fenwick(o) return f.SumPrefix(n) } func ScanInt(low, high int) int { return int(ScanInt64(int64(low), int64(high))) } var RemainingInput []byte func init() { var e error RemainingInput, e = ioutil.ReadAll(os.Stdin) if e != nil { panic(e) } } type Fenwick []int func (f *Fenwick) Init(N int) { if len(*f) == N { for n := 0; n < N; n++ { (*f)[n] = 0 } } else { *f = make(Fenwick, N) } } func (f *Fenwick) InitFrom(values []int) { if len(*f) != len(values) { *f = make(Fenwick, len(values)) } copy(*f, values) f.InitFromContent() } func (f Fenwick) InitFromContent() { for k, v := range f { j := k + LSB(k + 1) if j < len(f) { f[j] += v } } } func (f Fenwick) SumPrefix(n int) int { // Sum over values[:n] sum := 0 for n > 0 { sum += f[n-1] n -= LSB(n) } return sum } func (f Fenwick) SumRange(begin, end int) int { // sum over values[begin:end] Assert(begin <= end) sum := 0 for end > begin { sum += f[end-1] end -= LSB(end) } for begin > end { sum -= f[begin-1] begin -= LSB(begin) } return sum } func (f Fenwick) At(k int) int { // values[k] return f.SumRange(k, k + 1) } func (f Fenwick) Add(k, delta int) { // values[k] += delta for k < len(f) { f[k] += delta k += LSB(k + 1) } } func (f Fenwick) Set(k, value int) { // values[k] = value f.Add(k, value - f.At(k)) } func (f Fenwick) SearchSum(sum int) int { // First n such that SumPrefix(n) >= sum, or -1 if no such n // Assumes all values are >= 0 if sum <= 0 { return 0 } if len(f) == 0 { return -1 } bit := 1 << uint(bits.Len(uint(len(f))) - 1) n := 0 for ; bit > 0; bit >>= 1 { k := n + bit - 1 if k < len(f) { if x := f[k]; x < sum { n += bit sum -= x } } } if n == len(f) { return -1 } return n + 1 } func ScanInt64(low, high int64) int64 { x := Btoi(ScanToken()) Assert(low <= x && x <= high || !CheckInput) return x } func LSB(x int) int { return x & -x } func Btoi(s []byte) int64 { if s[0] == '-' { x := Btou(s[1:]) Assert(x <= - math.MinInt64) return - int64(x) } else { x := Btou(s) Assert(x <= math.MaxInt64) return int64(x) } } var CheckInput = true func ScanToken() []byte { for n, b := range RemainingInput { if b == ' ' || b == '\t' || b == '\r' { continue } if b == '\n' { Assert(!CheckInput) continue } RemainingInput = RemainingInput[n:] break } Assert(len(RemainingInput) > 0) n := 1 for ; n < len(RemainingInput); n++ { b := RemainingInput[n] if b == ' ' || b == '\t' || b == '\r' || b == '\n' { break } } token := RemainingInput[:n] RemainingInput = RemainingInput[n:] return token } func Btou(s []byte) uint64 { Assert(len(s) > 0) var x uint64 for _, d := range s { Assert('0' <= d && d <= '9') d -= '0' if x >= math.MaxUint64 / 10 { Assert(x == math.MaxUint64 / 10 && d <= math.MaxUint64 % 10) } x = x * 10 + uint64(d) } return x }