#pragma region Macros // #pragma GCC target("avx2") #pragma GCC optimize("O3") // #pragma GCC optimize("unroll-loops") #include #define ll long long #define ld long double #define rep2(i, a, b) for(ll i = a; i <= b; ++i) #define rep(i, n) for(ll i = 0; i < n; ++i) #define rep3(i, a, b) for(ll i = a; i >= b; --i) #define pii pair #define pll pair #define pb push_back #define eb emplace_back #define vi vector #define vll vector #define vpi vector #define vpll vector #define overload2(_1, _2, name, ...) name #define vec(type, name, ...) vector name(__VA_ARGS__) #define VEC(type, name, size) \ vector name(size); \ IN(name) #define vv(type, name, h, ...) vector> name(h, vector(__VA_ARGS__)) #define VV(type, name, h, w) \ vector> name(h, vector(w)); \ IN(name) #define vvv(type, name, h, w, ...) vector>> name(h, vector>(w, vector(__VA_ARGS__))) #define vvvv(type, name, a, b, c, ...) \ vector>>> name(a, vector>>(b, vector>(c, vector(__VA_ARGS__)))) #define mt make_tuple #define fi first #define se second #define all(c) begin(c), end(c) #define lb(c, x) distance((c).begin(), lower_bound(all(c), (x))) #define ub(c, x) distance((c).begin(), upper_bound(all(c), (x))) using namespace std; constexpr pii dx4[4] = {pii{1, 0}, pii{0, 1}, pii{-1, 0}, pii{0, -1}}; constexpr pii dx8[8] = {{1, 0}, {1, 1}, {0, 1}, {-1, 1}, {-1, 0}, {-1, -1}, {0, -1}, {1, -1}}; const string YESNO[2] = {"NO", "YES"}; const string YesNo[2] = {"No", "Yes"}; const string yesno[2] = {"no", "yes"}; void YES(bool t = 1) { cout << YESNO[t] << endl; } void Yes(bool t = 1) { cout << YesNo[t] << endl; } void yes(bool t = 1) { cout << yesno[t] << endl; } template using vc = vector; template using vvc = vector>; template using vvvc = vector>; template using vvvvc = vector>; template using pq = priority_queue; template using pqg = priority_queue, greater>; #define si(c) (int)(c).size() #define INT(...) \ int __VA_ARGS__; \ IN(__VA_ARGS__) #define LL(...) \ ll __VA_ARGS__; \ IN(__VA_ARGS__) #define STR(...) \ string __VA_ARGS__; \ IN(__VA_ARGS__) #define CHR(...) \ char __VA_ARGS__; \ IN(__VA_ARGS__) #define DBL(...) \ double __VA_ARGS__; \ IN(__VA_ARGS__) int scan() { return getchar(); } void scan(int &a) { cin >> a; } void scan(long long &a) { cin >> a; } void scan(char &a) { cin >> a; } void scan(double &a) { cin >> a; } void scan(string &a) { cin >> a; } template void scan(pair &p) { scan(p.first), scan(p.second); } template void scan(vector &); template void scan(vector &a) { for(auto &i : a) scan(i); } template void scan(T &a) { cin >> a; } void IN() {} template void IN(Head &head, Tail &...tail) { scan(head); IN(tail...); } template inline bool chmax(T &a, const S &b) { return (a < b ? a = b, 1 : 0); } template inline bool chmin(T &a, const S &b) { return (a > b ? a = b, 1 : 0); } vi iota(int n) { vi a(n); iota(all(a), 0); return a; } template vi iota(vector &a, bool greater = false) { vi res(a.size()); iota(all(res), 0); sort(all(res), [&](int i, int j) { if(greater) return a[i] > a[j]; return a[i] < a[j]; }); return res; } #define UNIQUE(x) sort(all(x)), x.erase(unique(all(x)), x.end()) template T POW(T x, int n) { T res = 1; for(; n; n >>= 1, x *= x) if(n & 1) res *= x; return res; } vector factor(ll x) { vector ans; for(ll i = 2; i * i <= x; i++) if(x % i == 0) { ans.push_back({i, 1}); while((x /= i) % i == 0) ans.back().second++; } if(x != 1) ans.push_back({x, 1}); return ans; } template vector divisor(T x) { vector ans; for(T i = 1; i * i <= x; i++) if(x % i == 0) { ans.pb(i); if(i * i != x) ans.pb(x / i); } return ans; } template void zip(vector &x) { vector y = x; sort(all(y)); for(int i = 0; i < x.size(); ++i) { x[i] = lb(y, x[i]); } } int topbit(signed t) { return t == 0 ? -1 : 31 - __builtin_clz(t); } int topbit(ll t) { return t == 0 ? -1 : 63 - __builtin_clzll(t); } int lowbit(signed a) { return a == 0 ? 32 : __builtin_ctz(a); } int lowbit(ll a) { return a == 0 ? 64 : __builtin_ctzll(a); } // int allbit(int n) { return (1 << n) - 1; } ll allbit(ll n) { return (1LL << n) - 1; } int popcount(signed t) { return __builtin_popcount(t); } int popcount(ll t) { return __builtin_popcountll(t); } bool ispow2(int i) { return i && (i & -i) == i; } int in() { int x; cin >> x; return x; } ll lin() { unsigned long long x; cin >> x; return x; } template pair operator-(const pair &x, const pair &y) { return pair(x.fi - y.fi, x.se - y.se); } template pair operator+(const pair &x, const pair &y) { return pair(x.fi + y.fi, x.se + y.se); } template ll operator*(const pair &x, const pair &y) { return (ll)x.fi * y.fi + (ll)x.se * y.se; } template struct edge { int from, to; T cost; int id; edge(int to, T cost) : from(-1), to(to), cost(cost) {} edge(int from, int to, T cost) : from(from), to(to), cost(cost) {} edge(int from, int to, T cost, int id) : from(from), to(to), cost(cost), id(id) {} edge &operator=(const int &x) { to = x; return *this; } operator int() const { return to; } }; template using Edges = vector>; using Tree = vector>; using Graph = vector>; template using Wgraph = vector>>; Graph getG(int n, int m = -1, bool directed = false, int margin = 1) { Tree res(n); if(m == -1) m = n - 1; while(m--) { int a, b; cin >> a >> b; a -= margin, b -= margin; res[a].emplace_back(b); if(!directed) res[b].emplace_back(a); } return move(res); } template Wgraph getWg(int n, int m = -1, bool directed = false, int margin = 1) { Wgraph res(n); if(m == -1) m = n - 1; while(m--) { int a, b; T c; cin >> a >> b >> c; a -= margin, b -= margin; res[a].emplace_back(b, c); if(!directed) res[b].emplace_back(a, c); } return move(res); } #define i128 __int128_t #define ull unsigned long long int #define TEST \ INT(testcases); \ while(testcases--) template ostream &operator<<(ostream &os, const vector &v) { for(auto it = begin(v); it != end(v); ++it) { if(it == begin(v)) os << *it; else os << " " << *it; } return os; } template ostream &operator<<(ostream &os, const pair &p) { os << p.first << " " << p.second; return os; } template string to_string(pair p) { return "(" + to_string(p.first) + "," + to_string(p.second) + ")"; } template string to_string(A v) { if(v.empty()) return "{}"; string ret = "{"; for(auto &x : v) ret += to_string(x) + ","; ret.back() = '}'; return ret; } string to_string(string s) { return "\"" + s + "\""; } void dump() { cerr << endl; } template void dump(Head head, Tail... tail) { cerr << to_string(head) << " "; dump(tail...); } #define endl '\n' #ifdef _LOCAL #undef endl #define debug(x) \ cout << #x << ": "; \ dump(x) #else #define debug(x) #endif template static constexpr T inf = numeric_limits::max() / 2; struct Setup_io { Setup_io() { ios_base::sync_with_stdio(0), cin.tie(0), cout.tie(0); cout << fixed << setprecision(15); } } setup_io; #define drop(s) cout << #s << endl, exit(0) #pragma endregion struct SuccinctIndexableDictionary { size_t length; size_t blocks; vector bit, sum; SuccinctIndexableDictionary() {} SuccinctIndexableDictionary(size_t _length) { length = _length; blocks = (length + 31) >> 5; bit.assign(blocks, 0U); sum.assign(blocks, 0U); } void set(int k) { bit[k >> 5] |= 1U << (k & 31); } void build() { sum[0] = 0U; for(int i = 1; i < blocks; i++) { sum[i] = sum[i - 1] + __builtin_popcount(bit[i - 1]); } } bool operator[](int k) const { return (bool((bit[k >> 5] >> (k & 31)) & 1)); } int rank(int k) { return (sum[k >> 5] + __builtin_popcount(bit[k >> 5] & ((1U << (k & 31)) - 1))); } int rank(bool val, int k) { return (val ? rank(k) : k - rank(k)); } int select(bool val, int k) { if(k < 0 || rank(val, length) <= k) return (-1); int low = 0, high = length; while(high - low > 1) { int mid = (low + high) >> 1; if(rank(val, mid) >= k + 1) high = mid; else low = mid; } return (high - 1); } int select(bool val, int i, int l) { return select(val, i + rank(val, l)); } }; template struct WaveletMatrix { size_t length; SuccinctIndexableDictionary matrix[MAXLOG]; int zs[MAXLOG]; int buff1[MAXLOG], buff2[MAXLOG]; int freq_dfs(int d, int l, int r, T val, T a, T b) { if(l == r) return 0; if(d == MAXLOG) return (a <= val && val < b) ? r - l : 0; T nv = 1ULL << (MAXLOG - d - 1) | val, nnv = ((1ULL << (MAXLOG - d - 1)) - 1) | nv; if(nnv < a || b <= val) return 0; if(a <= val && nnv < b) return r - l; int lc = matrix[d].rank(1, l), rc = matrix[d].rank(1, r); return freq_dfs(d + 1, l - lc, r - rc, val, a, b) + freq_dfs(d + 1, lc + zs[d], rc + zs[d], nv, a, b); } WaveletMatrix(vector data) { length = data.size(); vector l(length), r(length); for(int depth = 0; depth < MAXLOG; depth++) { matrix[depth] = SuccinctIndexableDictionary(length + 1); int left = 0, right = 0; for(int i = 0; i < length; i++) { bool k = (data[i] >> (MAXLOG - depth - 1)) & 1; if(k) r[right++] = data[i], matrix[depth].set(i); else l[left++] = data[i]; } zs[depth] = left; matrix[depth].build(); swap(l, data); for(int i = 0; i < right; i++) data[left + i] = r[i]; } } T access(int k) { int ret = 0; bool bit; for(int depth = 0; depth < MAXLOG; depth++) { bit = matrix[depth][k]; ret = (ret << 1) | bit; k = matrix[depth].rank(bit, k) + zs[depth] * bit; } return (ret); } int rank(T val, int k) { int l = 0, r = k; for(int depth = 0; depth < MAXLOG; depth++) { buff1[depth] = l, buff2[depth] = r; bool bit = (val >> (MAXLOG - depth - 1)) & 1; l = matrix[depth].rank(bit, l) + zs[depth] * bit; r = matrix[depth].rank(bit, r) + zs[depth] * bit; } return (r - l); } int select(T val, int kth) { rank(val, length); for(int depth = MAXLOG - 1; depth >= 0; depth--) { bool bit = (val >> (MAXLOG - depth - 1)) & 1; kth = matrix[depth].select(bit, kth, buff1[depth]); if(kth >= buff2[depth] || kth < 0) return (-1); kth -= buff1[depth]; } return (kth); } int select(T val, int k, int l) { return select(val, k + rank(val, l)); } int quantile(int left, int right, int kth) { if(right - left <= kth || kth < 0) return (-1); T ret = 0; for(int depth = 0; depth < MAXLOG; depth++) { int l = matrix[depth].rank(1, left); int r = matrix[depth].rank(1, right); if(r - l > kth) { left = l + zs[depth]; right = r + zs[depth]; ret |= 1ULL << (MAXLOG - depth - 1); } else { kth -= r - l; left -= l; right -= r; } } return ret; } int rangefreq(int left, int right, T lower, T upper) { return freq_dfs(0, left, right, 0, lower, upper); } }; int main() { INT(n); VEC(int, a, n); // WaveletMatrix mat(a); rep(i, n) a[i]--; a.eb(a[n - 2]); ll ans = 0; vi t(n), s(n); rep(i, n) { if(a[i] < a[i + 1]) { int mi = a[i + 1]; if(i) chmin(mi, a[i - 1]); t[a[i]] = mi; s[a[i]] = n; } else { int ma = a[i + 1]; if(i) chmax(ma, a[i - 1]); s[a[i]] = ma; t[a[i]] = -1; } } WaveletMatrix T(t), S(s); // dump(t, s); rep(i, n) { if(t[a[i]] >= 0) { int k = t[a[i]]; ans += T.rangefreq(0, k, a[i] + 1, n); ans += S.rangefreq(0, k, 0, a[i]); } else { int k = s[a[i]]; ans += T.rangefreq(k + 1, n, a[i] + 1, n); ans += S.rangefreq(k + 1, n, 0, a[i]); } } cout << (ans - n) / 2 << endl; }