#include using namespace std; template struct modint { unsigned long long x; modint() : x(0) {} modint(long long arg) { arg %= m; if (arg < 0) { x = arg + m; } else { x = arg; } } modint& operator+= (const modint& other) { x += other.x; if (x >= m) { x -= m; } return *this; } modint& operator*= (const modint& other) { x = (x * other.x) % m; return *this; } modint& operator-= (const modint& other) { x += m - other.x; if (x >= m) { x -= m; } return *this; } modint operator+ (const modint& other) const { modint tmp = *this; tmp += other; return tmp; } modint operator- (const modint& other) const { modint tmp = *this; tmp -= other; return tmp; } modint operator* (const modint& other) const { modint tmp = *this; tmp *= other; return tmp; } explicit operator unsigned long long () const { return x; } modint& operator++ () { ++x; if (x == m) { x = 0; } return *this; } modint& operator-- () { if (x == 0) { x = m-1; } else { --x; } return *this; } modint operator++ (int) { modint tmp = *this; ++*this; return tmp; } modint operator-- (int) { modint tmp = *this; --*this; return tmp; } bool operator== (const modint& other) const { return x == other.x; } bool operator!= (const modint& other) const { return x != other.x; } modint operator^ (unsigned long long arg) const { if (arg == 0) { return 1; } if (arg == 1) { return x; } auto t = *this ^ (arg >> 1); t *= t; if (arg & 1) { t *= *this; } return t; } modint inv(unsigned long long exp = m - 2) const { return *this ^ exp; } }; const unsigned long long MOD = 1'000'000'007; typedef modint mint; typedef long long ll; mint pp2(ll x) { if (x < 0) { return 0; } return mint(2).inv() * x * (x+1); } mint pp3(ll x) { if (x < 0) { return 0; } return mint(6).inv() * x * (x+1) * (x+2); } mint ex_parno(int x) { return mint(24).inv() * x * (x+2) * (2*x+5); } mint ex_neparno(int x) { return mint(24).inv() * (x+1) * (x+3) * (2*x+1); } mint ex_general(int x) { return x % 2 ? ex_neparno(x) : ex_parno(x); } mint cross_fall(int a, int b) { // ab + (a-1)(b-1) + ... if (a > b) { swap(a, b); } return mint(6).inv() * a * (a+1) * (3*b + 1 - a); } // a > b // Sum[ (a+b-2i) * (a+b-2i+1) / 2 , {i, 0, a-1}] mint ona_kul_formula(ll a, ll b) { return mint(6).inv() * b * (3*a*a + 9*a + b*b + 5); } // suma traje dok a ne padne na 0 mint dok_a_ne_padne_na_0(ll a, ll b) { if (b < 0) { b = 0; } if (a <= 0) { return 0; } if (a > b) { mint ret = ona_kul_formula(a, b); ret += pp3(a-b); return ret; } else { return ona_kul_formula(b, a); } } // suma traje dok oba ne padnu na 0 mint dok_ima_nesto(ll a, ll b) { if (a < b) { swap(a, b); } if (b < 0) { b = 0; } if (a <= 0) { return 0; } mint ret = ona_kul_formula(a, b); ret += pp3(a - b); return ret; } void asert(bool x) { cerr << (x ? "OK" : "FAILED") << '\n'; } void test_dve_ruzne_formule() { asert(dok_a_ne_padne_na_0(1, 4).x == 15); asert(dok_a_ne_padne_na_0(2, 5).x == 43); asert(dok_a_ne_padne_na_0(3, 3).x == 34); asert(dok_a_ne_padne_na_0(5, 2).x == 53); asert(dok_ima_nesto(1, 4).x == 25); asert(dok_ima_nesto(2, 5).x == 53); asert(dok_ima_nesto(3, 3).x == 34); asert(dok_ima_nesto(5, 2).x == 53); } // p je ovo sto je zaglavljeno levo od 4 // q je ovo sto je desno od 4 a pre wrap-a // s je ovo sto je posle wrap-a mint pqs_solver(ll p, ll q, ll s) { if (s > p+q+1) { // dodaj sve mint ret = dok_a_ne_padne_na_0(p+q+1, s); // izbaci p ret -= pp3(p); // izbaci qs ret -= dok_ima_nesto(q, s); // nepravedno sam izbacio visak ret += pp3(s-(p+q+1)); return ret; } else { mint ret = dok_a_ne_padne_na_0(p+q+1, s); // izbaci p ret -= pp3(p); // izbaci q-s ret -= dok_ima_nesto(q, s); return ret; } } mint pqs_solver_2(ll p, ll q, ll s) { if (s > p+q+2) { // dodaj sve mint ret = dok_a_ne_padne_na_0(p+q+2, s); // izbaci p ret -= pp3(p); // izbaci qs ret -= dok_ima_nesto(q, s); // nepravedno sam izbacio visak ret += pp3(s-(p+q+2)); return ret; } else { mint ret = dok_a_ne_padne_na_0(p+q+2, s); // izbaci p ret -= pp3(p); // izbaci q-s ret -= dok_ima_nesto(q, s); return ret; } } vector transform(vector a) { int n = a.size(); vector> d(n, vector(n, 0)); for (int i=0; i b; b.reserve(n*(n+1) / 2); for (int k=0; k> n; vector a(n); for (int& x : a) { cin >> x; } vector> b; for (int rep=0; rep<3; rep++) { for (int i=0; i s; vector r(3*n, 3*n), l(3*n, -1); // prvi desno veci ili jednak for (int i=0; i<3*n; i++) { while (s.size() && b[s.back()] <= b[i]) { r[s.back()] = i; s.pop_back(); } s.push_back(i); } // isto s druge strane s.clear(); for (int i=3*n-1; i>=0; i--) { while (s.size() && b[s.back()] < b[i]) { l[s.back()] = i; s.pop_back(); } s.push_back(i); } vector kl(l.begin() + n, l.begin()+2*n); vector kr(r.begin() + n, r.begin()+2*n); mint sol = 0; for (int i=n; i<2*n; i++) { int l = kl[i-n]; int r = kr[i-n]; int bi = b[i].first; int slucaj = 0; // ni jedan ni drugi se ne overextenduju // ovaj slucaj je ok i proveren je if (l >= n && r < 2*n) { slucaj = 1; int p = i-l-1; int q = r-i-1; sol += pp3(p+q+1) * bi; sol -= pp3(p) * bi; sol -= pp3(q) * bi; } // overextend u desno ali ne u levo else if (l >= n && r >= 2*n) { slucaj = 2; int p = i-l-1; int q = 2*n-i-1; int s = r-2*n; //cerr << "try2 " << p << ' ' << q << ' ' << s << '\n'; sol += pqs_solver(p, q, s-1) * bi; } // overextend u levo ali ne u desno else if (l < n && r < 2*n) { slucaj = 3; // sol += mint(i-(n-1)) * (r-i) * bi; int p = n-l-1; int q = i-n; int s = r-i-1; //cerr << "try3 " << p << ' ' << q << ' ' << s << '\n'; // prvo parce sol += mint(q+1) * (s+1) * bi; if (s > 0 && q > 0) { sol += pqs_solver_2(s-1, q-1, p) * bi; } else if (s > 0 || q > 0) { sol += pqs_solver(max(0, s-1), max(0, q-1), p) * bi; } } // lepotannn else { slucaj = 4; int x = i-n; int y = 2*n - i - 1; //cerr << "try4 " << x << ' ' << y << '\n'; sol += pp2(n * (n+1ll) / 2) * bi; sol -= pp2(x) * bi; // opadajuce sume sol -= dok_ima_nesto(y, x-1) * bi; } //cerr << i << ' ' << slucaj << ' ' << l << ' ' << r << ' ' << sol.x << '\n'; } cout << sol.x << '\n'; }