/** * date : 2021-01-29 22:29:27 */ #define NDEBUG using namespace std; // intrinstic #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include // utility namespace Nyaan { using ll = long long; using i64 = long long; using u64 = unsigned long long; using i128 = __int128_t; using u128 = __uint128_t; template using V = vector; template using VV = vector>; using vi = vector; using vl = vector; using vd = V; using vs = V; using vvi = vector>; using vvl = vector>; template struct P : pair { template P(Args... args) : pair(args...) {} using pair::first; using pair::second; T &x() { return first; } const T &x() const { return first; } U &y() { return second; } const U &y() const { return second; } P &operator+=(const P &r) { first += r.first; second += r.second; return *this; } P &operator-=(const P &r) { first -= r.first; second -= r.second; return *this; } P &operator*=(const P &r) { first *= r.first; second *= r.second; return *this; } P operator+(const P &r) const { return P(*this) += r; } P operator-(const P &r) const { return P(*this) -= r; } P operator*(const P &r) const { return P(*this) *= r; } }; using pl = P; using pi = P; using vp = V; constexpr int inf = 1001001001; constexpr long long infLL = 4004004004004004004LL; template int sz(const T &t) { return t.size(); } template void mem(T (&a)[N], int c) { memset(a, c, sizeof(T) * N); } template inline bool amin(T &x, U y) { return (y < x) ? (x = y, true) : false; } template inline bool amax(T &x, U y) { return (x < y) ? (x = y, true) : false; } template int lb(const vector &v, const T &a) { return lower_bound(begin(v), end(v), a) - begin(v); } template int ub(const vector &v, const T &a) { return upper_bound(begin(v), end(v), a) - begin(v); } constexpr long long TEN(int n) { long long ret = 1, x = 10; for (; n; x *= x, n >>= 1) ret *= (n & 1 ? x : 1); return ret; } template pair mkp(const T &t, const U &u) { return make_pair(t, u); } template vector mkrui(const vector &v, bool rev = false) { vector ret(v.size() + 1); if (rev) { for (int i = int(v.size()) - 1; i >= 0; i--) ret[i] = v[i] + ret[i + 1]; } else { for (int i = 0; i < int(v.size()); i++) ret[i + 1] = ret[i] + v[i]; } return ret; }; template vector mkuni(const vector &v) { vector ret(v); sort(ret.begin(), ret.end()); ret.erase(unique(ret.begin(), ret.end()), ret.end()); return ret; } template vector mkord(int N, F f) { vector ord(N); iota(begin(ord), end(ord), 0); sort(begin(ord), end(ord), f); return ord; } template vector reord(const vector &v, const vector &ord) { int N = v.size(); vector ret(N); for (int i = 0; i < N; i++) ret[i] = v[ord[i]]; return ret; }; template vector mkiota(int N) { vector ret(N); iota(begin(ret), end(ret), 0); return ret; } template vector mkinv(vector &v, int max_val = -1) { if (max_val < (int)v.size()) max_val = v.size() - 1; vector inv(max_val + 1, -1); for (int i = 0; i < (int)v.size(); i++) inv[v[i]] = i; return inv; } } // namespace Nyaan // bit operation namespace Nyaan { __attribute__((target("popcnt"))) inline int popcnt(const u64 &a) { return _mm_popcnt_u64(a); } __attribute__((target("bmi"))) inline int lsb(const u64 &a) { return _tzcnt_u64(a); } __attribute__((target("bmi"))) inline int ctz(const u64 &a) { return _tzcnt_u64(a); } __attribute__((target("lzcnt"))) inline int msb(const u64 &a) { return 63 - _lzcnt_u64(a); } __attribute__((target("lzcnt"))) inline int clz64(const u64 &a) { return _lzcnt_u64(a); } template inline int gbit(const T &a, int i) { return (a >> i) & 1; } template inline void sbit(T &a, int i, bool b) { a ^= (gbit(a, i) == b ? 0 : (T(b) << i)); } constexpr long long PW(int n) { return 1LL << n; } constexpr long long MSK(int n) { return (1LL << n) - 1; } } // namespace Nyaan // inout namespace Nyaan { template ostream &operator<<(ostream &os, const pair &p) { os << p.first << " " << p.second; return os; } template istream &operator>>(istream &is, pair &p) { is >> p.first >> p.second; return is; } template ostream &operator<<(ostream &os, const vector &v) { int s = (int)v.size(); for (int i = 0; i < s; i++) os << (i ? " " : "") << v[i]; return os; } template istream &operator>>(istream &is, vector &v) { for (auto &x : v) is >> x; return is; } void in() {} template void in(T &t, U &... u) { cin >> t; in(u...); } void out() { cout << "\n"; } template void out(const T &t, const U &... u) { cout << t; if (sizeof...(u)) cout << sep; out(u...); } void outr() {} template void outr(const T &t, const U &... u) { cout << t; outr(u...); } struct IoSetupNya { IoSetupNya() { cin.tie(nullptr); ios::sync_with_stdio(false); cout << fixed << setprecision(15); cerr << fixed << setprecision(7); } } iosetupnya; } // namespace Nyaan // debug namespace DebugImpl { template struct is_specialize : false_type {}; template struct is_specialize< U, typename conditional::type> : true_type {}; template struct is_specialize< U, typename conditional::type> : true_type {}; template struct is_specialize::value, void>> : true_type { }; void dump(const char& t) { cerr << t; } void dump(const string& t) { cerr << t; } template ::value, nullptr_t> = nullptr> void dump(const U& t) { cerr << t; } template void dump(const T& t, enable_if_t::value>* = nullptr) { string res; if (t == Nyaan::inf) res = "inf"; if (is_signed::value) if (t == -Nyaan::inf) res = "-inf"; if (sizeof(T) == 8) { if (t == Nyaan::infLL) res = "inf"; if (is_signed::value) if (t == -Nyaan::infLL) res = "-inf"; } if (res.empty()) res = to_string(t); cerr << res; } template void dump(const pair&); template void dump(const pair&); template void dump(const T& t, enable_if_t::value>* = nullptr) { cerr << "[ "; for (auto it = t.begin(); it != t.end();) { dump(*it); cerr << (++it == t.end() ? "" : ", "); } cerr << " ]"; } template void dump(const pair& t) { cerr << "( "; dump(t.first); cerr << ", "; dump(t.second); cerr << " )"; } template void dump(const pair& t) { cerr << "[ "; for (int i = 0; i < t.second; i++) { dump(t.first[i]); cerr << (i == t.second - 1 ? "" : ", "); } cerr << " ]"; } void trace() { cerr << endl; } template void trace(Head&& head, Tail&&... tail) { cerr << " "; dump(head); if (sizeof...(tail) != 0) cerr << ","; trace(forward(tail)...); } } // namespace DebugImpl #ifdef NyaanDebug #define trc(...) \ do { \ cerr << "## " << #__VA_ARGS__ << " = "; \ DebugImpl::trace(__VA_ARGS__); \ } while (0) #else #define trc(...) #endif // macro #define each(x, v) for (auto&& x : v) #define each2(x, y, v) for (auto&& [x, y] : v) #define all(v) (v).begin(), (v).end() #define rep(i, N) for (long long i = 0; i < (long long)(N); i++) #define repr(i, N) for (long long i = (long long)(N)-1; i >= 0; i--) #define rep1(i, N) for (long long i = 1; i <= (long long)(N); i++) #define repr1(i, N) for (long long i = (N); (long long)(i) > 0; i--) #define reg(i, a, b) for (long long i = (a); i < (b); i++) #define regr(i, a, b) for (long long i = (b)-1; i >= (a); i--) #define repc(i, a, cond) for (long long i = (a); (cond); i++) #define enm(i, val, vec) \ for (long long i = 0; i < (long long)(vec).size(); i++) \ if (auto& val = vec[i]; false) \ ; \ else #define ini(...) \ int __VA_ARGS__; \ in(__VA_ARGS__) #define inl(...) \ long long __VA_ARGS__; \ in(__VA_ARGS__) #define ins(...) \ string __VA_ARGS__; \ in(__VA_ARGS__) #define inc(...) \ char __VA_ARGS__; \ in(__VA_ARGS__) #define in2(s, t) \ for (int i = 0; i < (int)s.size(); i++) { \ in(s[i], t[i]); \ } #define in3(s, t, u) \ for (int i = 0; i < (int)s.size(); i++) { \ in(s[i], t[i], u[i]); \ } #define in4(s, t, u, v) \ for (int i = 0; i < (int)s.size(); i++) { \ in(s[i], t[i], u[i], v[i]); \ } #define die(...) \ do { \ Nyaan::out(__VA_ARGS__); \ return; \ } while (0) namespace Nyaan { void solve(); } int main() { Nyaan::solve(); } // #include // struct bit_vector { using u32 = uint32_t; using i64 = int64_t; using u64 = uint64_t; static constexpr u32 w = 64; vector block; vector count; u32 n, zeros; inline u32 get(u32 i) const { return u32(block[i / w] >> (i % w)) & 1u; } inline void set(u32 i) { block[i / w] |= 1LL << (i % w); } bit_vector() {} bit_vector(int _n) { init(_n); } __attribute__((optimize("O3,unroll-loops"))) void init(int _n) { n = zeros = _n; block.resize(n / w + 1, 0); count.resize(block.size(), 0); } __attribute__((target("popcnt"))) void build() { for (u32 i = 1; i < block.size(); ++i) count[i] = count[i - 1] + _mm_popcnt_u64(block[i - 1]); zeros = rank0(n); } inline u32 rank0(u32 i) const { return i - rank1(i); } __attribute__((target("bmi2,popcnt"))) inline u32 rank1(u32 i) const { return count[i / w] + _mm_popcnt_u64(_bzhi_u64(block[i / w], i % w)); } }; template struct WaveletMatrix { using u32 = uint32_t; using i64 = int64_t; using u64 = uint64_t; struct BIT { u32 N; vector data; BIT() = default; BIT(int size) { init(size); } void init(int size) { N = size; data.assign(N + 1, 0); } __attribute__((target("bmi"))) void add(u32 k, T x) { for (++k; k <= N; k += _blsi_u32(k)) data[k] += x; } __attribute__((target("bmi"))) T sum(u32 k) const { T ret = T(); for (; k; k = _blsr_u32(k)) ret += data[k]; return ret; } __attribute__((target("bmi"))) T sum(int l, int r) const { T ret = T(); while (l != r) { if (l < r) { ret += data[r]; r = _blsr_u32(r); } else { ret -= data[l]; l = _blsr_u32(l); } } return ret; } }; using P = pair; int n, lg; vector bv; vector bit; vector

ps; vector ys; WaveletMatrix() {} void add_point(S x, S y) { ps.emplace_back(x, y); ys.emplace_back(y); } __attribute__((optimize("O3"))) void build() { sort(begin(ps), end(ps)); ps.erase(unique(begin(ps), end(ps)), end(ps)); n = ps.size(); sort(begin(ys), end(ys)); ys.erase(unique(begin(ys), end(ys)), end(ys)); vector cur(n), nxt(n); for (int i = 0; i < n; ++i) cur[i] = yid(ps[i].second); lg = __lg(max(n, 1)) + 1; bv.assign(lg, n); bit.assign(lg, n); for (int h = lg - 1; h >= 0; --h) { for (int i = 0; i < n; ++i) if ((cur[i] >> h) & 1) bv[h].set(i); bv[h].build(); array it{begin(nxt), begin(nxt) + bv[h].zeros}; for (int i = 0; i < n; ++i) *it[bv[h].get(i)]++ = cur[i]; swap(cur, nxt); } } int xid(S x) const { return lower_bound( begin(ps), end(ps), make_pair(x, S()), [](const P& a, const P& b) { return a.first < b.first; }) - begin(ps); } int yid(S y) const { return lower_bound(begin(ys), end(ys), y) - begin(ys); } void add(S x, S y, T val) { int i = lower_bound(begin(ps), end(ps), P{x, y}) - begin(ps); for (int h = lg - 1; h >= 0; --h) { int i0 = bv[h].rank0(i); if (bv[h].get(i)) i += bv[h].zeros - i0; else i = i0; bit[h].add(i, val); } } T sum(int l, int r, u32 upper) const { T res = 0; for (int h = lg; h--;) { int l0 = bv[h].rank0(l), r0 = bv[h].rank0(r); if ((upper >> h) & 1) { res += bit[h].sum(l0, r0); l += bv[h].zeros - l0; r += bv[h].zeros - r0; } else { l = l0, r = r0; } } return res; } T sum(S lx, S ly, S rx, S ry) const { int l = xid(lx), r = xid(rx); return sum(l, r, yid(ry)) - sum(l, r, yid(ly)); } }; template struct BinaryIndexedTree { int N; vector data; BinaryIndexedTree() = default; BinaryIndexedTree(int size) { init(size); } void init(int size) { N = size + 2; data.assign(N + 1, 0); } // get sum of [0,k] T sum(int k) const { if (k < 0) return 0; // return 0 if k < 0 T ret = 0; for (++k; k > 0; k -= k & -k) ret += data[k]; return ret; } // getsum of [l,r] inline T sum(int l, int r) const { return sum(r) - sum(l - 1); } // get value of k inline T operator[](int k) const { return sum(k) - sum(k - 1); } // data[k] += x void add(int k, T x) { for (++k; k < N; k += k & -k) data[k] += x; } // range add x to [l,r] void imos(int l, int r, T x) { add(l, x); add(r + 1, -x); } // minimize i s.t. sum(i) >= w int lower_bound(T w) { if (w <= 0) return 0; int x = 0; for (int k = 1 << __lg(N); k; k >>= 1) { if (x + k <= N - 1 && data[x + k] < w) { w -= data[x + k]; x += k; } } return x; } // minimize i s.t. sum(i) > w int upper_bound(T w) { if (w < 0) return 0; int x = 0; for (int k = 1 << __lg(N); k; k >>= 1) { if (x + k <= N - 1 && data[x + k] <= w) { w -= data[x + k]; x += k; } } return x; } }; /** * @brief Binary Indexed Tree(Fenwick Tree) * @docs docs/data-structure/binary-indexed-tree.md */ using namespace Nyaan; bool kado(ll a, ll b, ll c) { return a != b and a != c and b != c and (max({a, b, c}) == b or min({a, b, c}) == b); } void Nyaan::solve() { ini(N); vl a(N); in(a); vp up, lw; rep(i, N - 2) { if (max({a[i], a[i + 1], a[i + 2]}) == a[i + 1]) { int sc = max({a[i], a[i + 2]}); up.emplace_back(sc + 1, a[i + 1]); } else { int sc = min({a[i], a[i + 2]}); lw.emplace_back(sc - 1, a[i + 1]); } } if (a[0] < a[1]) lw.emplace_back(a[1] - 1, a[0]); else up.emplace_back(a[1] + 1, a[0]); if (a[N - 1] < a[N - 2]) lw.emplace_back(a[N - 2] - 1, a[N - 1]); else up.emplace_back(a[N - 2] + 1, a[N - 1]); sort(all(up)); sort(all(lw), greater<>()); ll ans = 0; // 以上同士 { BinaryIndexedTree bit(N + 10); each2(i, j, up) { ans += bit.sum(i, N + 1); bit.add(j, 1); } } trc(ans); // 以下同士 { BinaryIndexedTree bit(N + 10); each2(i, j, lw) { ans += bit.sum(0, i); bit.add(j, 1); } } trc(ans); // 以上と以下のswap え~ どうやるんだっけこれ // 矩形クエリ? trc(up); trc(lw); WaveletMatrix wm; each2(i, j, up) wm.add_point(i, j); wm.build(); each2(i, j, up) wm.add(i, j, 1); each2(i, j, lw) { ans += wm.sum(0, 0, j + 1, i + 1); } out(ans); }