__author__ = 'Darren'

def solve():
    n = input()
    heights = map(int, raw_input().split(' '))
    max_height, max_index = -1, -1
    for i in range(n):
        if heights[i] > max_height:
            max_height = heights[i]
            max_index = i
    heights = heights[max_index:] + heights[:max_index]
    heights.append(max_height)

    left = [0 for i in range(n+1)]
    center = [0 for i in range(n+1)]
    right = [0 for i in range(n+1)]
    for i in range(1, n):
        left[i] = i - 1
        while left[i] > 0 and heights[i] >= heights[left[i]]:
            left[i] = left[left[i]]
    for i in range(n-1, -1, -1):
        right[i] = i + 1
        while right[i] < n and heights[i] > heights[right[i]]:
            right[i] = right[right[i]]
        if right[i] < n and heights[i] == heights[right[i]]:
            center[i] = center[right[i]] + 1
            right[i] = right[right[i]]

    total_pair = 0
    for i in range(n):
        total_pair += center[i]
        if heights[i] < max_height:
            if left[i] == 0 and right[i] == n:
                total_pair += 1
            else:
                total_pair += 2

    print(total_pair)

if __name__ == '__main__':
    solve()


__author__ = 'Darren'

def solve():
    n = int(input())
    heights = list(map(int, input().split()))
    max_height, max_index = -1, -1
    for i, height in enumerate(heights):
        if height > max_height:
            max_height = height
            max_index = i
    heights = heights[max_index:] + heights[:max_index]
    heights.append(max_height)

    left = [0 for i in range(n+1)]
    center = [0 for i in range(n+1)]
    right = [0 for i in range(n+1)]
    for i in range(1, n):
        left[i] = i - 1
        while left[i] > 0 and heights[i] >= heights[left[i]]:
            left[i] = left[left[i]]
    for i in range(n-1, -1, -1):
        right[i] = i + 1
        while right[i] < n and heights[i] > heights[right[i]]:
            right[i] = right[right[i]]
        if right[i] < n and heights[i] == heights[right[i]]:
            center[i] = center[right[i]] + 1
            right[i] = right[right[i]]

    total_pair = 0
    for i in range(n):
        total_pair += center[i]
        if heights[i] < max_height:
            if left[i] == 0 and right[i] == n:
                total_pair += 1
            else:
                total_pair += 2

    print(total_pair)

if __name__ == '__main__':
    solve()


#!/usr/bin/env python

def main():
    n = input()
    c, l, r = [0]*(n+1), [0]*(n+1), [0]*(n+1)
    h = map(int, raw_input().split(' '))
    x = 0
    for i in xrange(n):
        if h[i] > h[x]:
            x = i
    h = h[x:]+h[0:x]
    h.append(h[0])
    for i in xrange(n-1, -1, -1):
        r[i] = i+1
        while r[i] < n and h[i] > h[r[i]]:
            r[i] = r[r[i]]
        if r[i] < n and h[i] == h[r[i]]:
            c[i] = c[r[i]]+1
            r[i] = r[r[i]]
    ans = 0
    for i in xrange(n):
        ans += c[i]
        if h[i] < h[0]:
            l[i] = i-1
            while l[i] > 0 and h[i] >= h[l[i]]:
                l[i] = l[l[i]]
            ans += 2
            if l[i] == 0 and r[i] == n:
                ans -= 1
    print(ans)

main()


n = input()
h = map(int, raw_input().split()) * 2
i = h.index(max(h))
h = h[i : i + n + 1]
l, r, c = [[0] * (n + 1) for _ in range(3)]
for i, v in enumerate(h):
	t = i - 1
	while t >= 0 and h[t] < v:
		t = l[t]
	if t >= 0 and h[t] == v:
		c[i] = c[t] + 1
		t = l[t]
	l[i] = t
for i, v in enumerate(reversed(h)):
	i = n - i
	t = i + 1
	while t <= n and h[t] <= v:
		t = r[t]
	r[i] = t
print sum(1 + (u > 0 or v < n) for u, v in zip(l, r) if u != -1) + sum(c[ : n])


n = int(raw_input())
list1 = list(map(int,raw_input().split()))
#print(list1)
result = 0
for i in range(n-1):
    a = list1[i]
    for j in range(i+1,n):
        b = list1[j]
        #print(a,b)
        if j == i + 1:
            result += 1
            #print(result)
            continue
        else:
            max1 = max(list1[i+1:j])
        if i == 0 and j == n -1:
            result += 1
            #print(result)
            continue
        else:
            max2 = max(list1[:i] + list1[j+1:])
        #print(max1,max2)
        if a >= min(max1,max2) and b>= min(max1,max2):
            result += 1
        #print(result)
print(result)


n = input()
h = map(int, raw_input().split()) * 2
i = h.index(max(h))
h = h[i : i + n + 1]
l, r, c = [[0] * (n + 1) for _ in range(3)]
for i, v in enumerate(h):
    t = i - 1
    while t >= 0 and h[t] < v:
        t = l[t]
    if t >= 0 and h[t] == v:
        c[i] = c[t] + 1
        t = l[t]
    l[i] = t
for i, v in enumerate(reversed(h)):
    i = n - i
    t = i + 1
    while t <= n and h[t] <= v:
        t = r[t]
    r[i] = t
print sum(1 + (u > 0 or v < n) for u, v in zip(l, r) if u != -1) + sum(c[ : n])


n = input()
h = map(int, raw_input().split(' '))
i = h.index(max(h))
h = h[i : ] + h[ : i]
h.append(h[0])
l = [0] * (n + 1)
r = [0] * (n + 1)
c = [0] * (n + 1)
d = []
for i, v in enumerate(h):
	while d and h[d[-1]] < v:
		d.pop()
	t = -1
	if d and h[d[-1]] == v:
		t = c[d[-1]]
		d.pop()
	l[i] = d[-1] if d else -1
	c[i] = t + 1
	d.append(i)
d = []
for i, v in enumerate(reversed(h)):
	while d and h[d[-1]] < v:
		d.pop()
	t = 0
	if d and h[d[-1]] == v:
		t = c[d[-1]]
		d.pop()
	i = n - i
	r[i] = d[-1] if d else n + 1
	d.append(i)
print sum(1 + (u > 0 or v < n) for u, v in zip(l, r) if u != -1) + sum(c[ : n])


n = input()
h = map(int, raw_input().split(' '))
i = h.index(max(h))
h = h[i : ] + h[ : i]
h.append(h[0])
l = [0] * (n + 1)
r = [0] * (n + 1)
c = [0] * (n + 1)
for i, v in enumerate(h):
	l[i] = i - 1
	while l[i] >= 0 and h[l[i]] < v:
		l[i] = l[l[i]]
	if l[i] >= 0 and h[l[i]] == v:
		c[i] = c[l[i]] + 1
		l[i] = l[l[i]]
for i, v in enumerate(reversed(h)):
	i = n - i
	r[i] = i + 1
	while r[i] <= n and h[r[i]] <= v:
		r[i] = r[r[i]]
print sum(1 + (u > 0 or v < n) for u, v in zip(l, r) if u != -1) + sum(c[ : n])


n = input()
h = map(int, raw_input().split()) * 2
i = h.index(max(h))
h = h[i : i + n + 1]
l, r, c = [[0] * (n + 1) for _ in range(3)]
d = []
for i, v in enumerate(h):
	while d and d[-1][0] < v:
		d.pop()
	t = 0
	if d and d[-1][0] == v:
		t = d[-1][1]
		d.pop()
	l[i] = d[-1][2] if d else -1
	c[i] = t
	d.append((v, t + 1, i))
d = []
for i, v in enumerate(h[ : : -1]):
	while d and d[-1][0] < v:
		d.pop()
	t = 0
	if d and d[-1][0] == v:
		t = d[-1][1]
		d.pop()
	i = n - i
	r[i] = d[-1][2] if d else n + 1
	d.append((v, t + 1, i))
print sum(1 + (u > 0 or v < n) for u, v in zip(l, r) if u != -1) + sum(c[ : n])


n = input()
h = map(int, raw_input().split(' '))
i = h.index(max(h))
h = h[i : ] + h[ : i]
h.append(h[0])
l = [0] * (n + 1)
r = [0] * (n + 1)
c = [0] * (n + 1)
d = []
for i, v in enumerate(h):
	while d and d[-1][0] < v:
		d.pop()
	t = 0
	if d and d[-1][0] == v:
		t = d[-1][1]
		d.pop()
	l[i] = d[-1][2] if d else -1
	c[i] = t
	d.append((v, t + 1, i))
d = []
for i, v in enumerate(h[ : : -1]):
	while d and d[-1][0] < v:
		d.pop()
	t = 0
	if d and d[-1][0] == v:
		t = d[-1][1]
		d.pop()
	i = n - i
	r[i] = d[-1][2] if d else n + 1
	d.append((v, t + 1, i))
print sum(1 + (u > 0 or v < n) for u, v in zip(l, r) if u != -1) + sum(c[ : n])


n = input()
h = map(int, raw_input().split(' ')) * 2
i = h.index(max(h))
h = h[i : i + n + 1]
l, r, c = [[0] * (n + 1) for _ in range(3)]
for i, v in enumerate(h):
	t = i - 1
	while t >= 0 and h[t] < v:
		t = l[t]
	if t >= 0 and h[t] == v:
		c[i] = c[t] + 1
		t = l[t]
	l[i] = t
for i, v in enumerate(reversed(h)):
	i = n - i
	t = i + 1
	while t <= n and h[t] <= v:
		t = r[t]
	r[i] = t
print sum(1 + (u > 0 or v < n) for u, v in zip(l, r) if u != -1) + sum(c[ : n])


n = input()
h = map(int, raw_input().split()) * 2
i = h.index(max(h))
h = h[i : i + n + 1]
l, r, c = [[0] * (n + 1) for _ in range(3)]
d = []
for i, v in enumerate(h):
	while d and d[-1][0] < v:
		d.pop()
	t = 0
	if d and d[-1][0] == v:
		t = d[-1][1]
		d.pop()
	l[i] = d[-1][2] if d else -1
	c[i] = t
	d.append((v, t + 1, i))
d = []
for i, v in enumerate(h[ : : -1]):
	while d and d[-1][0] < v:
		d.pop()
	t = 0
	if d and d[-1][0] == v:
		t = d[-1][1]
		d.pop()
	i = n - i
	r[i] = d[-1][2] if d else n + 1
	d.append((v, t + 1, i))
p = sum(c[ : n])
for u, v in zip(l, r):
	if u != -1:
		p += 1 + (u or v < n)
print p


n = input()
h = map(int, raw_input().split()) * 2
i = h.index(max(h))
h = h[i : i + n + 1]
l, r, c = [[0] * (n + 1) for _ in range(3)]
for i, v in enumerate(h):
	t = i - 1
	while t >= 0 and h[t] < v:
		t = l[t]
	if t >= 0 and h[t] == v:
		c[i] = c[t] + 1
		t = l[t]
	l[i] = t
for i, v in enumerate(h[ : : -1]):
	t = i - 1
	while t >= 0 and h[t] <= v:
		t = r[t]
	r[i] = t
print sum(1 + (u + v > 0) for u, v in zip(l, r[ : : -1]) if u != -1) + sum(c[ : n])


n = input()
h = map(int, raw_input().split())
i = h.index(max(h))
h = h[i : ] + h[ : i] + [h[i]]
l, r, c = [[0] * (n + 1) for _ in range(3)]
d = []
for i, v in enumerate(h):
	while d and d[-1][0] < v:
		d.pop()
	t = 0
	if d and d[-1][0] == v:
		t = d[-1][1]
		d.pop()
	l[i], c[i] = d[-1][2] if d else -1, t
	d.append((v, t + 1, i))
d = []
for i, v in enumerate(h[ : : -1]):
	i = n - i
	while d and d[-1][0] < v:
		d.pop()
	t = 0
	if d and d[-1][0] == v:
		t = d[-1][1]
		d.pop()
	r[i] = d[-1][2] if d else n + 1
	d.append((v, t + 1, i))
p = 0
for i, v in enumerate(l[ : n]):
	if v != -1:
		p += 1 + (v or r[i] < n)
	p += c[i]
print p


#!/usr/bin/env python

def main():
    n = input()
    c, l, r = [0]*(n+1), [0]*(n+1), [0]*(n+1)
    h = map(int, raw_input().split(' '))
    x = 0
    for i in xrange(n):
        if h[i] > h[x]:
            x = i
    h = h[x:]+h[0:x]
    h.append(h[0])
    for i in xrange(n-1, -1, -1):
        r[i] = i+1
        while r[i] < n and h[i] > h[r[i]]:
            r[i] = r[r[i]]
        if r[i] < n and h[i] == h[r[i]]:
            c[i] = c[r[i]]+1
            r[i] = r[r[i]]
    ans = 0
    for i in xrange(n):
        ans += c[i]
        if h[i] < h[0]:
            l[i] = i-1
            while l[i] > 0 and h[i] > h[l[i]]:
                l[i] = l[l[i]]
            ans += 2
            if l[i] == 0 and r[i] == n:
                ans -= 1
    print(ans)

main()


#!/usr/bin/env python

def main():
    n = input()
    c, l, r = [0]*(n+1), [0]*(n+1), [0]*(n+1)
    h = map(int, raw_input().split(' '))
    x = 0
    for i in xrange(n):
        if h[i] > h[x]:
            x = i
    h = h[x:]+h[0:x]
    h.append(h[0])
    for i in xrange(n-1, -1, -1):
        r[i] = i+1
        while r[i] < n and h[i] > h[r[i]]:
            r[i] = r[r[i]]
        if r[i] < n and h[i] == h[r[i]]:
            c[i] = c[r[i]]+1
    ans = 0
    for i in xrange(n):
        ans += c[i]
        if h[i] < h[0]:
            l[i] = i-1
            while l[i] > 0 and h[i] >= h[l[i]]:
                l[i] = l[l[i]]
            ans += 2
            if l[i] == 0 and r[i] == n:
                ans -= 1
    print(ans)

main()


#!/usr/bin/env python

def main():
    n = input()
    c, l, r = [0]*(n+1), [0]*(n+1), [0]*(n+1)
    h = map(int, raw_input().split(' '))
    x = 0
    for i in xrange(n):
        if h[i] > h[x]:
            x = i
    h = h[x:]+h[0:x]
    h.append(h[0])
    for i in xrange(n-1, -1, -1):
        r[i] = i+1
        while r[i] < n and h[i] > h[r[i]]:
            r[i] = r[r[i]]
        if r[i] < n and h[i] == h[r[i]]:
            c[i] = c[r[i]]+1
    ans = 0
    for i in xrange(n):
        ans += c[i]
        if h[i] < h[0]:
            l[i] = i-1
            while l[i] > 0 and h[i] > h[l[i]]:
                l[i] = l[l[i]]
            ans += 2
            if l[i] == 0 and r[i] == n:
                ans -= 1
    print(ans)

main()


n = input()
a = map(int, raw_input().split())
i = a.index(max(a))
a = [1 << 30] + a[i:] + a[:i]

f, g, t = [0], [1], 0
for i in xrange(1, n + 1):
	j, k = i - 1, 1
	while a[j] <= a[i]:
		if a[j] == a[i]: k += g[j]
		t += g[j]
		j = f[j]
	if j: t += 1
	f.append(j)
	g.append(k)

h = 0
for i in xrange(n, 1, -1):
	if h <= a[i]
		h = a[i]
		if f[i] > 1: t += 1

print t


n = input()
a = map(int, raw_input().split())
i = a.index(max(a))
a = [1 << 30] + a[i:] + a[:i]

f, g, t = [0], [1], 0
for i in xrange(1, n + 1):
	j, k = i - 1, 1
	while a[j] <= a[i]:
		if a[j] == a[i]: k += g[j]
		t += g[j]
		j = f[j]
	if j: t += 1
	f.append(j)
	g.append(k)

h = 0
for i in xrange(n, 1, -1):
	if h <= a[i]:
		h = a[i]
		if f[i] > 1: t += 1

print t


n = input()
a = map(int, raw_input().split())
i = a.index(max(a))
a = [1 << 30] + a[i:] + a[:i]
#print a

f, g, t = [0], [1], 0
for i in xrange(1, n + 1):
	j, k = i - 1, 1
	while a[j] <= a[i]:
		if a[j] == a[i]: k += g[j]
		t += g[j]
		j = f[j]
	if j: t += 1
	f.append(j)
	g.append(k)
#print f,g

h = 0
for i in xrange(n, 1, -1):
	if h <= a[i]:
		h = a[i]
		if f[i] > 1: t += 1

print t


#include <stdio.h>
#include <string.h>
#include <stdlib.h>
#define MAXN 1000000
typedef long long ll;
int a[MAXN + 1];
int temp[MAXN];
int st[MAXN + 1];
int cnt[MAXN + 1];
ll max(ll a, ll b) {
    return a > b ? a : b;
}
int main() {
    int n, maxID = 0;
    scanf("%d", &n);
    for (int i = 0; i < n; ++i) {
        scanf("%d", temp + i);
        if (temp[maxID] < temp[i]) maxID = i;
    }
    memcpy(a, temp + maxID, sizeof(int) * (n - maxID));
    memcpy(a + (n - maxID), temp, sizeof(int) * maxID);
    a[n] = a[0];
    ll ans = 0;
    int len = 0;
    st[0] = a[0];
    cnt[0] = 1;
    for (int i = 1; i <= n; ++i) {
        if (a[i] > st[len]) {
            while (a[i] > st[len]) {
                ans += (ll)(cnt[len] + 3) * cnt[len] / 2;
                --len;
            }
        }
        if (a[i] == st[len]) ++cnt[len];
        else { st[++len] = a[i]; cnt[len] = 1; }
    }
    if (cnt[0] == 2) ans -= cnt[1];
    printf("%I64d\n", ans + (ll)(cnt[0] - 2) * (cnt[0] - 1) / 2);
    return 0;
}


#include <stdio.h>      //printf()
#include <string.h>     //memcpy()
#define MAXN 1000000
typedef long long ll;
int a[MAXN];
int st[MAXN];
int cnt[MAXN];
ll max(ll a, ll b) {
    return a > b ? a : b;
}
int main() {
    int n, maxID = 0;
    scanf("%d", &n);
    for (int i = 0; i < n; ++i) {
        scanf("%d", a + i);
        if (a[maxID] < a[i]) maxID = i;
    }
    ll ans = 0;
    int len = 0;
    int id = maxID;
    st[0] = a[maxID];
    cnt[0] = 1;
    for (int i = 1; i <= n; ++i) {
        id = (id + 1) % n;
        while (a[id] > st[len]) {
            ans += (ll)(cnt[len] + 3) * cnt[len] / 2;
            --len;
        }
        if (a[id] == st[len]) ++cnt[len];
        else { st[++len] = a[id]; cnt[len] = 1; }
    }
    if (cnt[0] == 2) ans -= cnt[1];
    printf("%I64d\n", ans + (ll)(cnt[0] - 2) * (cnt[0] - 1) / 2);
    return 0;
}


#include <stdio.h>
#include <string.h>
//#include <stdlib.h>
#define MAXN 100000
typedef long long ll;
int a[MAXN + 1];
int temp[MAXN];
int st[MAXN + 1];
int cnt[MAXN + 1];
ll max(ll a, ll b) {
    return a > b ? a : b;
}
int main() {
    int n, maxID = 0;
    scanf("%d", &n);
    for (int i = 0; i < n; ++i) {
        scanf("%d", temp + i);
        if (temp[maxID] < temp[i]) maxID = i;
    }
    memcpy(a, temp + maxID, sizeof(int) * (n - maxID));
    memcpy(a + (n - maxID), temp, sizeof(int) * maxID);
    a[n] = a[0];
    ll ans = 0;
    int len = 0;
    st[0] = a[0];
    cnt[0] = 1;
    for (int i = 1; i <= n; ++i) {
        if (a[i] > st[len]) {
            int c = 0;
            while (a[i] > st[len]) {
                c += cnt[len];
                --len;
            }
            ans += c + 1;
            if (i == n && cnt[0] == 1) --ans;
        }
        if (a[i] == st[len]) ++cnt[len];
        else { st[++len] = a[i]; cnt[len] = 1; }
    }
    printf("%I64d\n", ans + (ll)(cnt[0] - 2) * (cnt[0] - 1) / 2);
    return 0;
}


#include <stdio.h>
#include <string.h>
//#include <stdlib.h>
#define MAXN 100000
typedef long long ll;
int a[MAXN + 1];
int temp[MAXN];
int st[MAXN + 1];
int cnt[MAXN + 1];
ll max(ll a, ll b) {
    return a > b ? a : b;
}
int main() {
    int n, maxID = 0;
    scanf("%d", &n);
    for (int i = 0; i < n; ++i) {
        scanf("%d", temp + i);
        if (temp[maxID] < temp[i]) maxID = i;
    }
    memcpy(a, temp + maxID, sizeof(int) * (n - maxID));
    memcpy(a + (n - maxID), temp, sizeof(int) * maxID);
    a[n] = a[0];
    ll ans = 0;
    int len = 0;
    st[0] = a[0];
    cnt[0] = 1;
    for (int i = 1; i <= n; ++i) {
        if (a[i] > st[len]) {
            while (a[i] > st[len]) {
                ans += (ll)(cnt[len] + 3) * cnt[len] / 2;
                --len;
            }
        }
        if (a[i] == st[len]) ++cnt[len];
        else { st[++len] = a[i]; cnt[len] = 1; }
    }
    if (cnt[0] == 2) --ans;
    printf("%I64d\n", ans + (ll)(cnt[0] - 2) * (cnt[0] - 1) / 2);
    return 0;
}


#include <stdio.h>
#include <string.h>
#include <stdlib.h>
#define MAXN 1000000
typedef long long ll;
int a[MAXN + 1];
int temp[MAXN];
int st[MAXN + 1];
int cnt[MAXN + 1];
ll max(ll a, ll b) {
    return a > b ? a : b;
}
int main() {
    int n, maxID = 0;
    scanf("%d", &n);
    for (int i = 0; i < n; ++i) {
        scanf("%d", temp + i);
        if (temp[maxID] < temp[i]) maxID = i;
    }
    memcpy(a, temp + maxID, sizeof(int) * (n - maxID));
    memcpy(a + (n - maxID), temp, sizeof(int) * maxID);
    a[n] = a[0];
    ll ans = 0;
    int len = 0;
    st[0] = a[0];
    cnt[0] = 1;
    for (int i = 1; i <= n; ++i) {
        if (a[i] > st[len]) {
            while (a[i] > st[len]) {
                ans += (ll)(cnt[len] + 3) * cnt[len] / 2;
                --len;
            }
        }
        if (a[i] == st[len]) ++cnt[len];
        else { st[++len] = a[i]; cnt[len] = 1; }
    }
    if (cnt[0] == 2) --ans;
    printf("%I64d\n", ans + (ll)(cnt[0] - 2) * (cnt[0] - 1) / 2);
    return 0;
}


#include <stdio.h>
#include <stdlib.h>
#define MAXN 100005
#define ll long long
int arr[MAXN];
int st[MAXN];
int cnt[MAXN];
ll max(ll a, ll b) {
    return a > b ? a : b;
}
int main() {
    int n, maxID = 0;
    scanf("%d", &n);
    for (int i = 0; i < n; ++i) {
        scanf("%d", arr + i);
        if (arr[maxID] < arr[i]) maxID = i;
    }
    int len = 1;
    ll ans = 0;
    st[len] = arr[maxID];
    cnt[len] = 1;
    for (int i = (maxID + 1) % n; i != maxID; i = (i + 1) % n) {
        if (st[len] < arr[i]) {
            while (st[len] < arr[i]) {
                ans += cnt[len] * (ll)(cnt[len] + 3) / 2;
                --len;
            }
        }
        if (st[len] != arr[i]) { st[++len] = arr[i]; cnt[len] = 1; }
        else ++cnt[len];
    }
    for (int i = 1; i < len; ++i) ans += (ll)(cnt[i] + 1) * cnt[i] / 2;
    ans += (ll)(cnt[len] - 1) * cnt[len] / 2;
    if (cnt[1] > 1) {
        cnt[1] = 1;
        len = 1;
        for (int i = (maxID + n - 1) % n; cnt[1] == 1; i = (i - 1 + n) % n) {
            if (st[len] < arr[i]) {
                while (st[len] < arr[i]) --len;
                if (len == 1) ans += cnt[2];
            }
            if (st[len] != arr[i]) {
                st[++len] = arr[i]; cnt[len] = 1;
            }
            else ++cnt[len];
        }
    }
    printf("%I64d\n", ans);
    return 0;
}


#include <stdio.h>
#include <string.h>
//#include <stdlib.h>
#define MAXN 100000
typedef long long ll;
int a[MAXN + 1];
int temp[MAXN];
int st[MAXN + 1];
int cnt[MAXN + 1];
ll max(ll a, ll b) {
    return a > b ? a : b;
}
int main() {
    int n, maxID = 0;
    scanf("%d", &n);
    for (int i = 0; i < n; ++i) {
        scanf("%d", temp + i);
        if (temp[maxID] < temp[i]) maxID = i;
    }
    memcpy(a, temp + maxID, sizeof(int) * (n - maxID));
    memcpy(a + (n - maxID), temp, sizeof(int) * maxID);
    a[n] = a[0];
    ll ans = 0;
    int len = 0;
    st[0] = a[0];
    cnt[0] = 1;
    for (int i = 1; i <= n; ++i) {
        if (a[i] > st[len]) {
            int c = 0;
            while (a[i] > st[len]) {
                c += cnt[len];
                --len;
            }
            ans += c + 1;
        }
        if (a[i] == st[len]) ++cnt[len];
        else { st[++len] = a[i]; cnt[len] = 1; }
    }
    printf("%I64d\n", ans + (ll)(cnt[0] - 2) * (cnt[0] - 1) / 2);
    return 0;
}


#include <stdio.h>
#include <stdlib.h>
#define MAXN 100005
int arr[MAXN];
int st[MAXN];
int cnt[MAXN];
typedef long long ll;
int main() {
    int n, maxID = 0;
    scanf("%d", &n);
    for (int i = 0; i < n; ++i) {
        scanf("%d", arr + i);
        if (arr[maxID] < arr[i]) maxID = i;
    }
    int len = 0;
    ll ans = 0;
    st[++len] = arr[maxID];
    cnt[len] = 1;
    for (int i = (maxID + 1) % n; i != maxID; i = (i + 1) % n) {
        if (st[len] < arr[i]) {
            ll t = 0;
            while (st[len] < arr[i]) {
                ans += cnt[len] * (ll)(cnt[len] - 1) / 2;
                t += cnt[len];
                --len;
            }
            ans += t * 2;
        }
        if (st[len] != arr[i]) { st[++len] = arr[i]; cnt[len] = 1; }
        else ++cnt[len];
    }
    ll t = 0;
    for (int i = 1; i <= len; ++i) t += cnt[i];
    printf("%I64d\n", ans + t * (t - 1) / 2);
    return 0;
}


#include <stdio.h>
#include <stdlib.h>
#define MAXN 100005
#define ll long long
int arr[MAXN];
int st[MAXN];
int cnt[MAXN];
ll max(ll a, ll b) {
    return a > b ? a : b;
}
int main() {
    int n, maxID = 0;
    scanf("%d", &n);
    for (int i = 0; i < n; ++i) {
        scanf("%d", arr + i);
        if (arr[maxID] < arr[i]) maxID = i;
    }
    int len = 1;
    ll ans = 0;
    st[len] = arr[maxID];
    cnt[len] = 1;
    for (int i = (maxID + 1) % n; i != maxID; i = (i + 1) % n) {
        if (st[len] < arr[i]) {
            while (st[len] < arr[i]) {
                ans += cnt[len] * (ll)(cnt[len] + 3) / 2;
                --len;
            }
        }
        if (st[len] != arr[i]) { st[++len] = arr[i]; cnt[len] = 1; }
        else ++cnt[len];
    }
    for (int i = 1; i < len; ++i) ans += (ll)(cnt[i] + 1) * cnt[i] / 2;
    ans += (ll)(cnt[len] - 1) * cnt[len] / 2;
    if (cnt[1] > 1) {
        cnt[1] = 1;
        len = 1;
        for (int i = (maxID + n - 1) % n; cnt[1] == 1; i = (i - 1 + n) % n) {
            while (st[len] < arr[i]) --len;
            if (st[len] != arr[i]) {
                if (len == 1) ++ans;
                st[++len] = arr[i]; cnt[len] = 1;
            }
            else ++cnt[len];
        }
    }
    printf("%I64d\n", ans);
    return 0;
}


#include <stdio.h>
#include <stdlib.h>
#define MAXN 100005
int arr[MAXN];
int st[MAXN];
int cnt[MAXN];
typedef long long ll;
ll max(ll a, ll b) {
    return a > b ? a : b;
}
int main() {
    int n, maxID = 0;
    scanf("%d", &n);
    for (int i = 0; i < n; ++i) {
        scanf("%d", arr + i);
        if (arr[maxID] < arr[i]) maxID = i;
    }
    int len = 1;
    ll ans = 0;
    st[len] = arr[maxID];
    cnt[len] = 1;
    for (int i = (maxID + 1) % n; i != maxID; i = (i + 1) % n) {
        if (st[len] < arr[i]) {
            while (st[len] < arr[i]) {
                ans += cnt[len] * (ll)(cnt[len] + 3) / 2;
                --len;
            }
        }
        if (st[len] != arr[i]) { st[++len] = arr[i]; cnt[len] = 1; }
        else ++cnt[len];
    }
    for (int i = 1; i < len; ++i) ans += (ll)(cnt[i] + 1) * cnt[i] / 2;
    ans += (ll)(cnt[len] - 1) * cnt[len] / 2;
    if (cnt[1] > 1) {
        cnt[1] = 1;
        len = 1;
        for (int i = (maxID - 1) % n; cnt[1] == 1; i = (i - 1 + n) % n) {
            while (st[len] < arr[i]) --len;
            if (st[len] != arr[i]) {
                if (len == 1) ++ans;
                st[++len] = arr[i]; cnt[len] = 1;
            }
            else ++cnt[len];
        }
    }
    printf("%I64d\n", ans);
    return 0;
}


#include <stdio.h>
#include <stdlib.h>
#define MAXN 100005
int arr[MAXN];
int st[MAXN];
int cnt[MAXN];
typedef long long ll;
ll res(int beg, int n, int step) {
    int len = 1;
    ll ans = 0;
    st[len] = arr[beg];
    cnt[len] = 1;
    for (int i = (beg + step) % n; i != beg; i = (i + step + n) % n) {
        if (st[len] < arr[i]) {
            while (st[len] < arr[i]) {
                ans += cnt[len] * (ll)(cnt[len] + 3) / 2;
                --len;
            }
        }
        if (st[len] != arr[i]) { st[++len] = arr[i]; cnt[len] = 1; }
        else ++cnt[len];
    }
    for (int i = 1; i < len; ++i) ans += (ll)(cnt[i] + 1) * cnt[i] / 2;
    return ans + (ll)(cnt[len] - 1) * cnt[len] / 2;
}
ll max(ll a, ll b) {
    return a > b ? a : b;
}
int main() {
    int n, maxID = 0;
    scanf("%d", &n);
    for (int i = 0; i < n; ++i) {
        scanf("%d", arr + i);
        if (arr[maxID] < arr[i]) maxID = i;
    }
    ll ans = max(res(maxID, n, 1), res(maxID, n, -1));
    printf("%I64d\n", ans);
    return 0;
}


#include <stdio.h>      //printf()
#include <string.h>     //memcpy()
#define MAXN 1000000
typedef long long ll;
int a[MAXN + 1];
int temp[MAXN];
int st[MAXN + 1];
int cnt[MAXN + 1];
ll max(ll a, ll b) {
    return a > b ? a : b;
}
int main() {
    int n, maxID = 0;
    scanf("%d", &n);
    for (int i = 0; i < n; ++i) {
        scanf("%d", temp + i);
        if (temp[maxID] < temp[i]) maxID = i;
    }
    memcpy(a, temp + maxID, sizeof(int) * (n - maxID));
    memcpy(a + (n - maxID), temp, sizeof(int) * maxID);
    a[n] = a[0];
    ll ans = 0;
    int len = 0;
    st[0] = a[0];
    cnt[0] = 1;
    for (int i = 1; i <= n; ++i) {
        while (a[i] > st[len]) {
            ans += (ll)(cnt[len] + 3) * cnt[len] / 2;
            --len;
        }
        if (a[i] == st[len]) ++cnt[len];
        else { st[++len] = a[i]; cnt[len] = 1; }
    }
    if (cnt[0] == 2) ans -= cnt[1];
    printf("%I64d\n", ans + (ll)(cnt[0] - 2) * (cnt[0] - 1) / 2);
    return 0;
}


using System;
using System.Collections.Generic;
using System.Diagnostics;
using System.Globalization;
using System.IO;
using System.Linq;
using System.Text;
using System.Threading.Tasks;

namespace _5E
{
    class Program
    {
        public class DoubleLink
        {
            public long Data { get; set; }
            public DoubleLink PreviousLink { get; set; }
            public DoubleLink NextLink { get; set; }

            public DoubleLink(long data)
            {
                Data = data;
            }

            public override string ToString()
            {
                return Data.ToString();
            }
        }

        public class DoubleLinkedList
        {
            public long count = 0;
            private DoubleLink _first;
            public bool IsEmpty
            {
                get
                {
                    return _first == null;
                }
            }
            public DoubleLinkedList()
            {
                _first = null;
            }

            public DoubleLink Min()
            {
                DoubleLink link = _first;
                DoubleLink min = link;

                while (link.NextLink != _first)
                {
                    link = link.NextLink;
                    if (link.Data < min.Data)
                        min = link;
                }
                return min;
            }

            public void Remove(DoubleLink link)
            {
                if (link == link.PreviousLink)
                {
                    _first = null;
                }
                else
                {
                    DoubleLink prev = link.PreviousLink;
                    DoubleLink next = link.NextLink;
                    prev.NextLink = next;
                    next.PreviousLink = prev;

                    if (_first == link)
                        _first = prev;
                }
                count--;
            }

            public DoubleLink Insert(long data)
            {
                count++;
                DoubleLink link = new DoubleLink(data);
                DoubleLink next = _first == null ? link : _first;
                DoubleLink prev = _first == null ? link : _first.PreviousLink;

                link.NextLink = next;
                link.PreviousLink = prev;

                next.PreviousLink = link;
                prev.NextLink = link;

                _first = link;

                return link;
            }

            public DoubleLink Delete()
            {
                DoubleLink temp = _first;
                if (_first != null)
                {
                    _first = _first.NextLink;
                    if (_first != null)
                        _first.PreviousLink = null;
                }
                return temp;
            }

            public override string ToString()
            {
                DoubleLink currentLink = _first;
                StringBuilder builder = new StringBuilder();
                while (currentLink != null)
                {
                    builder.Append(currentLink);
                    currentLink = currentLink.NextLink;
                }
                return builder.ToString();
            }
        }

        static void Main(string[] args)
        {
            long result = 0;
            CultureInfo culture = new CultureInfo("en-US");

            long[] A = Console.ReadLine().Trim().Split(' ').Select(x => long.Parse(x, culture)).ToArray();
            long n = A[0];
            long[] data = Console.ReadLine().Trim().Split(' ').Select(x => long.Parse(x, culture)).ToArray();
            DoubleLinkedList list = new DoubleLinkedList();
            foreach (long d in data)
            {
                list.Insert(d);
            }

            while (list.count > 1)
            {
                DoubleLink min = list.Min();
                HashSet<DoubleLink> mins = new HashSet<DoubleLink>();
                HashSet<DoubleLink> visible = new HashSet<DoubleLink>();
                mins.Add(min);

                DoubleLink left = min;
                while (left.PreviousLink != min && left.PreviousLink.Data == min.Data)
                {
                    left = left.PreviousLink;
                    mins.Add(left);
                }

                left = left.PreviousLink;
                if (!mins.Contains(left))
                    visible.Add(left);

                DoubleLink right = min;
                while (right.NextLink != min && right.NextLink.Data == min.Data)
                {
                    right = right.NextLink;
                    mins.Add(right);
                }

                right = right.NextLink;
                if (!mins.Contains(right))
                    visible.Add(right);

                foreach (var d in mins)
                {
                    list.Remove(d);
                }
                long visibleCount = visible.Count;
                long minsCount = mins.Count;
                result += visibleCount * minsCount + minsCount * (minsCount - 1) / 2;
            }
            Console.WriteLine(result);
        }
    }
}


using System;
using System.Collections.Generic;
using System.Globalization;
using System.Linq;
using System.Text;
using System.Threading.Tasks;

namespace _5E
{
    class Program
    {
        public class DoubleLink
        {
            public long Data { get; set; }
            public DoubleLink PreviousLink { get; set; }
            public DoubleLink NextLink { get; set; }

            public DoubleLink(long data)
            {
                Data = data;
            }

            public override string ToString()
            {
                return Data.ToString();
            }
        }

        public class DoubleLinkedList
        {
            public long count = 0;
            private DoubleLink _first;
            public bool IsEmpty
            {
                get
                {
                    return _first == null;
                }
            }
            public DoubleLinkedList()
            {
                _first = null;
            }

            public DoubleLink Min()
            {
                DoubleLink link = _first;
                DoubleLink min = link;

                while (link.NextLink != _first)
                {
                    link = link.NextLink;
                    if (link.Data < min.Data)
                        min = link;
                }
                return min;
            }

            public void Remove(DoubleLink link)
            {
                if (link == link.PreviousLink)
                {
                    _first = null;
                }
                else
                {
                    DoubleLink prev = link.PreviousLink;
                    DoubleLink next = link.NextLink;
                    prev.NextLink = next;
                    next.PreviousLink = prev;

                    if (_first == link)
                        _first = prev;
                }
                count--;
            }

            public DoubleLink Insert(long data)
            {
                count++;
                DoubleLink link = new DoubleLink(data);
                DoubleLink next = _first == null ? link : _first;
                DoubleLink prev = _first == null ? link : _first.PreviousLink;

                link.NextLink = next;
                link.PreviousLink = prev;

                next.PreviousLink = link;
                prev.NextLink = link;

                _first = link;

                return link;
            }

            public DoubleLink Delete()
            {
                DoubleLink temp = _first;
                if (_first != null)
                {
                    _first = _first.NextLink;
                    if (_first != null)
                        _first.PreviousLink = null;
                }
                return temp;
            }

            public override string ToString()
            {
                DoubleLink currentLink = _first;
                StringBuilder builder = new StringBuilder();
                while (currentLink != null)
                {
                    builder.Append(currentLink);
                    currentLink = currentLink.NextLink;
                }
                return builder.ToString();
            }
        }

        static void Main(string[] args)
        {
            CultureInfo culture = new CultureInfo("en-US");

            long[] A = Console.ReadLine().Split(' ').Select(x => long.Parse(x, culture)).ToArray();
            long n = A[0];
            long[] data = Console.ReadLine().Split(' ').Select(x => long.Parse(x, culture)).ToArray();
            DoubleLinkedList list = new DoubleLinkedList();
            foreach (long d in data)
            {
                list.Insert(d);
            }
            long result = 0;

            while (list.count > 1)
            {
                DoubleLink min = list.Min();
                HashSet<DoubleLink> mins = new HashSet<DoubleLink>();
                HashSet<DoubleLink> visible = new HashSet<DoubleLink>();
                mins.Add(min);

                DoubleLink left = min;
                while (left.PreviousLink != min && left.PreviousLink.Data == min.Data)
                {
                    left = left.PreviousLink;
                    mins.Add(left);
                }

                left = left.PreviousLink;
                DoubleLink ln = left;
                if (!mins.Contains(ln))
                    while (left != min && left.Data <= ln.Data)
                    {
                        if (left.Data == ln.Data)
                            visible.Add(left);
                        else if (left.Data != min.Data)
                            break;
                        left = left.PreviousLink;
                    }

                DoubleLink right = min;
                while (right.NextLink != min && right.NextLink.Data == min.Data)
                {
                    right = right.NextLink;
                    mins.Add(right);
                }

                right = right.NextLink;
                DoubleLink rn = right;
                if (!mins.Contains(rn))
                    while (right != min && right.Data <= rn.Data)
                    {
                        if (right.Data == rn.Data)
                            visible.Add(right);
                        else if (right.Data != min.Data)
                            break;
                        right = right.NextLink;
                    }

                foreach (var d in mins)
                {
                    list.Remove(d);
                }
                result += visible.Count * mins.Count + mins.Count * (mins.Count - 1) / 2;
            }
            Console.WriteLine(result);
        }
    }
}


using System;
using System.Collections.Generic;
using System.Diagnostics;
using System.Globalization;
using System.IO;
using System.Linq;
using System.Text;
using System.Threading.Tasks;

namespace _5E
{
    class Program
    {
        public class DoubleLink
        {
            public int Data { get; set; }
            public bool Procesed = false;
            public DoubleLink PreviousLink { get; set; }
            public DoubleLink NextLink { get; set; }

            public DoubleLink(int data)
            {
                Data = data;
            }

            public override string ToString()
            {
                return Data.ToString();
            }
        }

        public class DoubleLinkedList
        {
            public int count = 0;
            private DoubleLink _first;
            public bool IsEmpty
            {
                get
                {
                    return _first == null;
                }
            }
            public DoubleLinkedList()
            {
                _first = null;
            }

            public DoubleLink Min()
            {
                DoubleLink link = _first;
                DoubleLink min = link;

                while (link.NextLink != _first)
                {
                    link = link.NextLink;
                    if (link.Data < min.Data)
                        min = link;
                }
                return min;
            }

            public void Remove(DoubleLink link)
            {
                if (link == link.PreviousLink)
                {
                    _first = null;
                }
                else
                {
                    DoubleLink prev = link.PreviousLink;
                    DoubleLink next = link.NextLink;
                    prev.NextLink = next;
                    next.PreviousLink = prev;

                    if (_first == link)
                        _first = prev;
                }
                count--;
            }

            public DoubleLink Insert(int data)
            {
                count++;
                DoubleLink link = new DoubleLink(data);
                DoubleLink next = _first == null ? link : _first;
                DoubleLink prev = _first == null ? link : _first.PreviousLink;

                link.NextLink = next;
                link.PreviousLink = prev;

                next.PreviousLink = link;
                prev.NextLink = link;

                _first = link;

                return link;
            }

            public DoubleLink Delete()
            {
                DoubleLink temp = _first;
                if (_first != null)
                {
                    _first = _first.NextLink;
                    if (_first != null)
                        _first.PreviousLink = null;
                }
                return temp;
            }

            public override string ToString()
            {
                DoubleLink currentLink = _first;
                StringBuilder builder = new StringBuilder();
                while (currentLink != null)
                {
                    builder.Append(currentLink);
                    currentLink = currentLink.NextLink;
                }
                return builder.ToString();
            }
        }

        static void Main(string[] args)
        {
            long result = 0;
            CultureInfo culture = new CultureInfo("en-US");

            int[] A = Console.ReadLine().Trim().Split(' ').Select(x => int.Parse(x, culture)).ToArray();
            int n = A[0];
            int[] data = Console.ReadLine().Trim().Split(' ').Select(x => int.Parse(x, culture)).ToArray();
            DoubleLinkedList list = new DoubleLinkedList();
            List<DoubleLink> links = new List<DoubleLink>(n);
            foreach (int d in data)
            {
                DoubleLink link = list.Insert(d);
                links.Add(link);
            }

            links.Sort((x, y) => x.Data - y.Data);

            int current = 0;

            while (list.count > 1)
            {
                while (links[current].Procesed)
                {
                    current++;
                }

                DoubleLink min = links[current++];
                min.Procesed = true;

                HashSet<DoubleLink> mins = new HashSet<DoubleLink>();
                HashSet<DoubleLink> visible = new HashSet<DoubleLink>();
                mins.Add(min);

                DoubleLink left = min;
                while (left.PreviousLink != min && left.PreviousLink.Data == min.Data)
                {
                    left = left.PreviousLink;
                    left.Procesed = true;
                    mins.Add(left);
                }

                left = left.PreviousLink;
                if (!mins.Contains(left))
                    visible.Add(left);

                DoubleLink right = min;
                while (right.NextLink != min && right.NextLink.Data == min.Data)
                {
                    right = right.NextLink;
                    right.Procesed = true;
                    mins.Add(right);
                }

                right = right.NextLink;
                if (!mins.Contains(right))
                    visible.Add(right);

                foreach (var d in mins)
                {
                    list.Remove(d);
                }
                long visibleCount = visible.Count;
                long minsCount = mins.Count;
                result += visibleCount * minsCount + minsCount * (minsCount - 1) / 2;
            }
            Console.WriteLine(result);
        }
    }
}


using System;
using System.Collections.Generic;
using System.Globalization;
using System.Linq;
using System.Text;
using System.Threading.Tasks;

namespace _5E
{
    class Program
    {
        public class DoubleLink
        {
            public long Data { get; set; }
            public DoubleLink PreviousLink { get; set; }
            public DoubleLink NextLink { get; set; }

            public DoubleLink(long data)
            {
                Data = data;
            }

            public override string ToString()
            {
                return Data.ToString();
            }
        }

        public class DoubleLinkedList
        {
            public long count = 0;
            private DoubleLink _first;
            public bool IsEmpty
            {
                get
                {
                    return _first == null;
                }
            }
            public DoubleLinkedList()
            {
                _first = null;
            }

            public DoubleLink Min()
            {
                DoubleLink link = _first;
                DoubleLink min = link;

                while (link.NextLink != _first)
                {
                    link = link.NextLink;
                    if (link.Data < min.Data)
                        min = link;
                }
                return min;
            }

            public void Remove(DoubleLink link)
            {
                if (link == link.PreviousLink)
                {
                    _first = null;
                }
                else
                {
                    DoubleLink prev = link.PreviousLink;
                    DoubleLink next = link.NextLink;
                    prev.NextLink = next;
                    next.PreviousLink = prev;

                    if (_first == link)
                        _first = prev;
                }
                count--;
            }

            public DoubleLink Insert(long data)
            {
                count++;
                DoubleLink link = new DoubleLink(data);
                DoubleLink next = _first == null ? link : _first;
                DoubleLink prev = _first == null ? link : _first.PreviousLink;

                link.NextLink = next;
                link.PreviousLink = prev;

                next.PreviousLink = link;
                prev.NextLink = link;

                _first = link;

                return link;
            }

            public DoubleLink Delete()
            {
                DoubleLink temp = _first;
                if (_first != null)
                {
                    _first = _first.NextLink;
                    if (_first != null)
                        _first.PreviousLink = null;
                }
                return temp;
            }

            public override string ToString()
            {
                DoubleLink currentLink = _first;
                StringBuilder builder = new StringBuilder();
                while (currentLink != null)
                {
                    builder.Append(currentLink);
                    currentLink = currentLink.NextLink;
                }
                return builder.ToString();
            }
        }

        static void Main(string[] args)
        {
            CultureInfo culture = new CultureInfo("en-US");

            long[] A = Console.ReadLine().Split(' ').Select(x => long.Parse(x, culture)).ToArray();
            long n = A[0];
            long[] data = Console.ReadLine().Split(' ').Select(x => long.Parse(x, culture)).ToArray();
            DoubleLinkedList list = new DoubleLinkedList();
            foreach (long d in data)
            {
                list.Insert(d);
            }
            long result = 0;

            while (list.count > 1)
            {
                DoubleLink min = list.Min();
                HashSet<DoubleLink> mins = new HashSet<DoubleLink>();
                HashSet<DoubleLink> visible = new HashSet<DoubleLink>();
                mins.Add(min);

                DoubleLink left = min;
                while (left.PreviousLink != min && left.PreviousLink.Data == min.Data)
                {
                    left = left.PreviousLink;
                    mins.Add(left);
                }

                left = left.PreviousLink;
                if (!mins.Contains(left))
                    visible.Add(left);

                DoubleLink right = min;
                while (right.NextLink != min && right.NextLink.Data == min.Data)
                {
                    right = right.NextLink;
                    mins.Add(right);
                }

                right = right.NextLink;
                if (!mins.Contains(right))
                    visible.Add(right);

                foreach (var d in mins)
                {
                    list.Remove(d);
                }
                result += visible.Count * mins.Count + mins.Count * (mins.Count - 1) / 2;
            }
            Console.WriteLine(result);
        }
    }
}


using System;
using System.Collections.Generic;
using System.Diagnostics;
using System.Globalization;
using System.IO;
using System.Linq;
using System.Text;
using System.Threading.Tasks;

namespace _5E
{
    class Program
    {
        public class DoubleLink
        {
            public int Data { get; set; }
            public bool Procesed = false;
            public DoubleLink PreviousLink { get; set; }
            public DoubleLink NextLink { get; set; }

            public DoubleLink(int data)
            {
                Data = data;
            }

            public override string ToString()
            {
                return Data.ToString();
            }
        }

        public class DoubleLinkedList
        {
            public int count = 0;
            private DoubleLink _first;
            public bool IsEmpty
            {
                get
                {
                    return _first == null;
                }
            }
            public DoubleLinkedList()
            {
                _first = null;
            }

            public DoubleLink Min()
            {
                DoubleLink link = _first;
                DoubleLink min = link;

                while (link.NextLink != _first)
                {
                    link = link.NextLink;
                    if (link.Data < min.Data)
                        min = link;
                }
                return min;
            }

            public void Remove(DoubleLink link)
            {
                if (link == link.PreviousLink)
                {
                    _first = null;
                }
                else
                {
                    DoubleLink prev = link.PreviousLink;
                    DoubleLink next = link.NextLink;
                    prev.NextLink = next;
                    next.PreviousLink = prev;

                    if (_first == link)
                        _first = prev;
                }
                count--;
            }

            public DoubleLink Insert(int data)
            {
                count++;
                DoubleLink link = new DoubleLink(data);
                DoubleLink next = _first == null ? link : _first;
                DoubleLink prev = _first == null ? link : _first.PreviousLink;

                link.NextLink = next;
                link.PreviousLink = prev;

                next.PreviousLink = link;
                prev.NextLink = link;

                _first = link;

                return link;
            }

            public DoubleLink Delete()
            {
                DoubleLink temp = _first;
                if (_first != null)
                {
                    _first = _first.NextLink;
                    if (_first != null)
                        _first.PreviousLink = null;
                }
                return temp;
            }

            public override string ToString()
            {
                DoubleLink currentLink = _first;
                StringBuilder builder = new StringBuilder();
                while (currentLink != null)
                {
                    builder.Append(currentLink);
                    currentLink = currentLink.NextLink;
                }
                return builder.ToString();
            }
        }

        static void Main(string[] args)
        {
            long result = 0;
            CultureInfo culture = new CultureInfo("en-US");

            int[] A = Console.ReadLine().Trim().Split(' ').Select(x => int.Parse(x, culture)).ToArray();
            int n = A[0];
            int[] data = Console.ReadLine().Trim().Split(' ').Select(x => int.Parse(x, culture)).ToArray();
            DoubleLinkedList list = new DoubleLinkedList();
            List<DoubleLink> links = new List<DoubleLink>(n);
            foreach (int d in data)
            {
                DoubleLink link = list.Insert(d);
                links.Add(link);
            }

            links.Sort((x, y) => x.Data - y.Data);

            int current = 0;

            while (list.count > 1)
            {
                while (links[current].Procesed)
                {
                    current++;
                }

                DoubleLink min = links[current++];
                HashSet<DoubleLink> mins = new HashSet<DoubleLink>();
                HashSet<DoubleLink> visible = new HashSet<DoubleLink>();
                mins.Add(min);

                DoubleLink left = min;
                while (left.PreviousLink != min && left.PreviousLink.Data == min.Data)
                {
                    left = left.PreviousLink;
                    mins.Add(left);
                }

                left = left.PreviousLink;
                if (!mins.Contains(left))
                    visible.Add(left);

                DoubleLink right = min;
                while (right.NextLink != min && right.NextLink.Data == min.Data)
                {
                    right = right.NextLink;
                    mins.Add(right);
                }

                right = right.NextLink;
                if (!mins.Contains(right))
                    visible.Add(right);

                foreach (var d in mins)
                {
                    list.Remove(d);
                }
                long visibleCount = visible.Count;
                long minsCount = mins.Count;
                result += visibleCount * minsCount + minsCount * (minsCount - 1) / 2;
            }
            Console.WriteLine(result);
        }
    }
}


using System;
using System.Collections.Generic;
using System.Globalization;
using System.Linq;
using System.Text;
using System.Threading.Tasks;

namespace _5E
{
    class Program
    {
        public class DoubleLink
        {
            public long Data { get; set; }
            public DoubleLink PreviousLink { get; set; }
            public DoubleLink NextLink { get; set; }

            public DoubleLink(long data)
            {
                Data = data;
            }

            public override string ToString()
            {
                return Data.ToString();
            }
        }

        public class DoubleLinkedList
        {
            public long count = 0;
            private DoubleLink _first;
            public bool IsEmpty
            {
                get
                {
                    return _first == null;
                }
            }
            public DoubleLinkedList()
            {
                _first = null;
            }

            public DoubleLink Min()
            {
                DoubleLink link = _first;
                DoubleLink min = link;

                while (link.NextLink != _first)
                {
                    link = link.NextLink;
                    if (link.Data < min.Data)
                        min = link;
                }
                return min;
            }

            public void Remove(DoubleLink link)
            {
                if (link == link.PreviousLink)
                {
                    _first = null;
                }
                else
                {
                    DoubleLink prev = link.PreviousLink;
                    DoubleLink next = link.NextLink;
                    prev.NextLink = next;
                    next.PreviousLink = prev;

                    if (_first == link)
                        _first = prev;
                }
                count--;
            }

            public DoubleLink Insert(long data)
            {
                count++;
                DoubleLink link = new DoubleLink(data);
                DoubleLink next = _first == null ? link : _first;
                DoubleLink prev = _first == null ? link : _first.PreviousLink;

                link.NextLink = next;
                link.PreviousLink = prev;

                next.PreviousLink = link;
                prev.NextLink = link;

                _first = link;

                return link;
            }

            public DoubleLink Delete()
            {
                DoubleLink temp = _first;
                if (_first != null)
                {
                    _first = _first.NextLink;
                    if (_first != null)
                        _first.PreviousLink = null;
                }
                return temp;
            }

            public override string ToString()
            {
                DoubleLink currentLink = _first;
                StringBuilder builder = new StringBuilder();
                while (currentLink != null)
                {
                    builder.Append(currentLink);
                    currentLink = currentLink.NextLink;
                }
                return builder.ToString();
            }
        }

        static void Main(string[] args)
        {
            CultureInfo culture = new CultureInfo("en-US");

            long[] A = Console.ReadLine().Split(' ').Select(x => long.Parse(x, culture)).ToArray();
            long n = A[0];
            long[] data = Console.ReadLine().Split(' ').Select(x => long.Parse(x, culture)).ToArray();
            DoubleLinkedList list = new DoubleLinkedList();
            foreach (long d in data)
            {
                list.Insert(d);
            }
            long result = 0;

            while (list.count > 1)
            {
                DoubleLink min = list.Min();
                HashSet<DoubleLink> mins = new HashSet<DoubleLink>();
                mins.Add(min);

                DoubleLink left = min;
                while (left.PreviousLink != min && left.PreviousLink.Data == min.Data)
                {
                    left = left.PreviousLink;
                    mins.Add(left);
                }

                DoubleLink right = min;
                while (right.NextLink != min && right.NextLink.Data == min.Data)
                {
                    right = right.NextLink;
                    mins.Add(right);
                }
                if (mins.Count <= list.count - 2)
                {
                    result += (mins.Count + 1) * (mins.Count + 2) / 2 - 1;
                }
                else if (mins.Count == list.count - 1)
                {
                    result += (mins.Count + 1) * (mins.Count) / 2;
                }
                else if (mins.Count == list.count)
                {
                    result += (mins.Count - 1) * (mins.Count) / 2;
                }
                foreach (var d in mins)
                {
                    list.Remove(d);
                }
            }
            Console.WriteLine(result);
        }
    }
}


using System;
using System.Collections.Generic;
using System.Globalization;
using System.Linq;
using System.Text;
using System.Threading.Tasks;

namespace _5E
{
    class Program
    {
        public class DoubleLink
        {
            public long Data { get; set; }
            public DoubleLink PreviousLink { get; set; }
            public DoubleLink NextLink { get; set; }

            public DoubleLink(long data)
            {
                Data = data;
            }

            public override string ToString()
            {
                return Data.ToString();
            }
        }

        public class DoubleLinkedList
        {
            public long count = 0;
            private DoubleLink _first;
            public bool IsEmpty
            {
                get
                {
                    return _first == null;
                }
            }
            public DoubleLinkedList()
            {
                _first = null;
            }

            public DoubleLink Min()
            {
                DoubleLink link = _first;
                DoubleLink min = link;

                while (link.NextLink != _first)
                {
                    link = link.NextLink;
                    if (link.Data < min.Data)
                        min = link;
                }
                return min;
            }

            public void Remove(DoubleLink link)
            {
                if (link == link.PreviousLink)
                {
                    _first = null;
                }
                else
                {
                    DoubleLink prev = link.PreviousLink;
                    DoubleLink next = link.NextLink;
                    prev.NextLink = next;
                    next.PreviousLink = prev;

                    if (_first == link)
                        _first = prev;
                }
                count--;
            }

            public DoubleLink Insert(long data)
            {
                count++;
                DoubleLink link = new DoubleLink(data);
                DoubleLink next = _first == null ? link : _first;
                DoubleLink prev = _first == null ? link : _first.PreviousLink;

                link.NextLink = next;
                link.PreviousLink = prev;

                next.PreviousLink = link;
                prev.NextLink = link;

                _first = link;

                return link;
            }

            public DoubleLink Delete()
            {
                DoubleLink temp = _first;
                if (_first != null)
                {
                    _first = _first.NextLink;
                    if (_first != null)
                        _first.PreviousLink = null;
                }
                return temp;
            }

            public override string ToString()
            {
                DoubleLink currentLink = _first;
                StringBuilder builder = new StringBuilder();
                while (currentLink != null)
                {
                    builder.Append(currentLink);
                    currentLink = currentLink.NextLink;
                }
                return builder.ToString();
            }
        }

        static void Main(string[] args)
        {
            CultureInfo culture = new CultureInfo("en-US");

            long[] A = Console.ReadLine().Split(' ').Select(x => long.Parse(x, culture)).ToArray();
            long n = A[0];
            long[] data = Console.ReadLine().Split(' ').Select(x => long.Parse(x, culture)).ToArray();
            DoubleLinkedList list = new DoubleLinkedList();
            foreach (long d in data)
            {
                list.Insert(d);
            }
            long result = 0;

            while (list.count > 1)
            {
                DoubleLink min = list.Min();
                HashSet<DoubleLink> mins = new HashSet<DoubleLink>();
                HashSet<DoubleLink> visible = new HashSet<DoubleLink>();
                mins.Add(min);

                DoubleLink left = min;
                while (left.PreviousLink != min && left.PreviousLink.Data == min.Data)
                {
                    left = left.PreviousLink;
                    mins.Add(left);
                }

                left = left.PreviousLink;
                DoubleLink ln = left;
                if (!mins.Contains(ln))
                    while (left != min && left.Data <= ln.Data)
                    {
                        if (left.Data == ln.Data)
                            visible.Add(left);
                        left = left.PreviousLink;
                    }

                DoubleLink right = min;
                while (right.NextLink != min && right.NextLink.Data == min.Data)
                {
                    right = right.NextLink;
                    mins.Add(right);
                }

                right = right.NextLink;
                DoubleLink rn = right;
                if (!mins.Contains(rn))
                    while (right != min && right.Data <= rn.Data)
                    {
                        if (right.Data == rn.Data)
                            visible.Add(right);
                        right = right.NextLink;
                    }

                foreach (var d in mins)
                {
                    list.Remove(d);
                }
                result += visible.Count * mins.Count + mins.Count * (mins.Count - 1) / 2;
            }
            Console.WriteLine(result);
        }
    }
}


using System;
using System.Collections.Generic;
using System.Globalization;
using System.Linq;
using System.Text;
using System.Threading.Tasks;

namespace _5E
{
    class Program
    {
        public class DoubleLink
        {
            public long Data { get; set; }
            public DoubleLink PreviousLink { get; set; }
            public DoubleLink NextLink { get; set; }

            public DoubleLink(long data)
            {
                Data = data;
            }

            public override string ToString()
            {
                return Data.ToString();
            }
        }

        public class DoubleLinkedList
        {
            public long count = 0;
            private DoubleLink _first;
            public bool IsEmpty
            {
                get
                {
                    return _first == null;
                }
            }
            public DoubleLinkedList()
            {
                _first = null;
            }

            public DoubleLink Min()
            {
                DoubleLink link = _first;
                DoubleLink min = link;

                while (link.NextLink != _first)
                {
                    link = link.NextLink;
                    if (link.Data < min.Data)
                        min = link;
                }
                return min;
            }

            public void Remove(DoubleLink link)
            {
                if (link == link.PreviousLink)
                {
                    _first = null;
                }
                else
                {
                    DoubleLink prev = link.PreviousLink;
                    DoubleLink next = link.NextLink;
                    prev.NextLink = next;
                    next.PreviousLink = prev;

                    if (_first == link)
                        _first = prev;
                }
                count--;
            }

            public DoubleLink Insert(long data)
            {
                count++;
                DoubleLink link = new DoubleLink(data);
                DoubleLink next = _first == null ? link : _first;
                DoubleLink prev = _first == null ? link : _first.PreviousLink;

                link.NextLink = next;
                link.PreviousLink = prev;

                next.PreviousLink = link;
                prev.NextLink = link;

                _first = link;

                return link;
            }

            public DoubleLink Delete()
            {
                DoubleLink temp = _first;
                if (_first != null)
                {
                    _first = _first.NextLink;
                    if (_first != null)
                        _first.PreviousLink = null;
                }
                return temp;
            }

            public override string ToString()
            {
                DoubleLink currentLink = _first;
                StringBuilder builder = new StringBuilder();
                while (currentLink != null)
                {
                    builder.Append(currentLink);
                    currentLink = currentLink.NextLink;
                }
                return builder.ToString();
            }
        }

        static void Main(string[] args)
        {
            CultureInfo culture = new CultureInfo("en-US");

            long[] A = Console.ReadLine().Split(' ').Select(x => long.Parse(x, culture)).ToArray();
            long n = A[0];
            long[] data = Console.ReadLine().Split(' ').Select(x => long.Parse(x, culture)).ToArray();
            DoubleLinkedList list = new DoubleLinkedList();
            foreach (long d in data)
            {
                list.Insert(d);
            }
            long result = 0;

            while (list.count > 1)
            {
                DoubleLink min = list.Min();
                HashSet<DoubleLink> mins = new HashSet<DoubleLink>();
                HashSet<DoubleLink> visible = new HashSet<DoubleLink>();
                mins.Add(min);

                DoubleLink left = min;
                while (left.PreviousLink != min && left.PreviousLink.Data == min.Data)
                {
                    left = left.PreviousLink;
                    mins.Add(left);
                }

                left = left.PreviousLink;
                DoubleLink ln = left;
                if (!mins.Contains(ln))
                    while (left != min && left.Data == ln.Data)
                    {
                        visible.Add(left);
                        left = left.PreviousLink;
                    }

                DoubleLink right = min;
                while (right.NextLink != min && right.NextLink.Data == min.Data)
                {
                    right = right.NextLink;
                    mins.Add(right);
                }

                right = right.NextLink;
                DoubleLink rn = right;
                if (!mins.Contains(rn))
                    while (right != min && right.Data == rn.Data)
                    {
                        visible.Add(right);
                        right = right.NextLink;
                    }

                foreach (var d in mins)
                {
                    list.Remove(d);
                }
                result += visible.Count * mins.Count + mins.Count * (mins.Count - 1) / 2;
            }
            Console.WriteLine(result);
        }
    }
}


using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.IO;

namespace CodeForces {
    class Cf {
        static void Main(string[] args) {
            SolveC5E();
            //Console.ReadLine();
        }

        static void SolveC5E() {
            int n = ReadInt();
            int[] array = ReadIntArray();
            int index = array.MaxIntIndex();
            if (index > 0) {
                int length = n - index;
                int[] temp = new int[length];
                Array.Copy(array, index, temp, 0, length);
                Array.Copy(array, 0, array, length, index);
                Array.Copy(temp, array, length);
            }
            ulong count = 0;
            int max = array[0];
            int maxCount = array.Count(item => item == max);
            Stack<int> stack = new Stack<int>();
            Dictionary<int, int> itemCount = new Dictionary<int, int>();
            for (int i = 1; i < n; ++i) {
                int current = array[i];
                if (current == max) {
                    stack.Clear();
                }
                else {
                    while (stack.Count > 0 && stack.Peek() < current) {
                        int popped = stack.Pop();
                        count += (ulong)itemCount[popped];
                        itemCount[popped] = 0;
                    }
                    if (stack.Count > 0 && stack.Peek() == current) {
                        int currentCount = itemCount[current];
                        count += (ulong)currentCount;
                        if (stack.Count > 1)
                            ++count;
                        ++itemCount[current];
                    }
                    else {
                        if (stack.Count > 0)
                            ++count;
                        stack.Push(current);
                        itemCount[current] = 1;
                    }
                }
            }
            int highest = int.MinValue;
            int lastMax = 0;
            int highest0index = 0;
            for (int i = 1; i < n; ++i) {
                int current = array[i];
                if (current == max) {
                    highest = int.MinValue;
                    for (int j = i - 1; j > lastMax; --j) {
                        if (array[j] >= highest) {
                            highest = array[j];
                            ++count;
                        }
                    }
                    lastMax = i;
                    highest = int.MinValue;
                }
                else if (current >= highest) {
                    if (lastMax == 0)
                        highest0index = i;
                    highest = current;
                    ++count;
                }
            }
            highest = int.MinValue;
            for (int i = n - 1; i > lastMax; --i) {
                if (i == highest0index) break;
                if (array[i] >= highest) {
                    highest = array[i];
                    ++count;
                }
            }
            count += ((ulong)maxCount * (ulong)(maxCount - 1)) >> 1;
            Console.WriteLine(count);
        }

        public static int[] ReadIntArray() {
            return Console.ReadLine().Split(' ').Select(x => int.Parse(x)).ToArray();
        }

        public static int ReadInt() {
            return int.Parse(Console.ReadLine());
        }
    }

    public static class Extensions {
        public static string Fill(this char c, int count) {
            char[] r = new char[count];
            for (int i = 0; i < count; ++i)
                r[i] = c;
            return new string(r);
        }

        public static int MaxIntIndex(this int[] array) {
            int max = array[0];
            int index = 0;
            for (int i = 1; i < array.Length; ++i) {
                if (array[i] > max) {
                    max = array[i];
                    index = i;
                }
            }
            return index;
        }

        public static void PrintToConsole<T>(this IEnumerable<T> arr) {
            foreach (T t in arr)
                Console.Write("{0} ", t);
        }
    }
}


using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.IO;

namespace CodeForces {
    class Cf {
        static void Main(string[] args) {
            SolveC5E();
            //Console.ReadLine();
        }

        static void SolveC5E() {
            int n = ReadInt();
            int[] array = ReadIntArray();
            int index = array.MaxIntIndex();
            if (index > 0) {
                int length = n - index;
                int[] temp = new int[length];
                Array.Copy(array, index, temp, 0, length);
                Array.Copy(array, 0, array, length, index);
                Array.Copy(temp, array, length);
            }
            int count = 0;
            int max = array[0];
            Stack<int> stack = new Stack<int>();
            stack.Push(array[0]);
            for (int i = 1; i < n; ++i) {
                int current = array[i];
                if (stack.Peek() >= current) {
                    stack.Push(current);
                }
                else {
                    int temp = 0;
                    while (stack.Peek() < current) {
                        stack.Pop();
                        ++temp;
                    }
                    if (temp > 1 && ((stack.Peek() != max) || (stack.Peek()==max && stack.Count>1)))
                        ++temp;
                    stack.Push(current);
                    count += temp;
                }
            }
            if (count == 0)
                ++count;
            Console.WriteLine(count + n - 1);
        }

        public static int[] ReadIntArray() {
            return Console.ReadLine().Split(' ').Select(x => int.Parse(x)).ToArray();
        }

        public static int ReadInt() {
            return int.Parse(Console.ReadLine());
        }
    }

    public static class Extensions {
        public static string Fill(this char c, int count) {
            char[] r = new char[count];
            for (int i = 0; i < count; ++i)
                r[i] = c;
            return new string(r);
        }

        public static int MaxIntIndex(this int[] array) {
            int max = array[0];
            int index = 0;
            for (int i = 1; i < array.Length; ++i) {
                if (array[i] > max) {
                    max = array[i];
                    index = i;
                }
            }
            return index;
        }

        public static void PrintToConsole<T>(this IEnumerable<T> arr) {
            foreach (T t in arr)
                Console.Write("{0} ", t);
        }
    }
}


using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.IO;

namespace CodeForces {
    class Cf {
        static void Main(string[] args) {
            SolveC5E();
            //Console.ReadLine();
        }

        static void SolveC5E() {
            int n = ReadInt();
            int[] array = ReadIntArray();
            int index = array.MaxIntIndex();
            if (index > 0) {
                int length = n - index;
                int[] temp = new int[length];
                Array.Copy(array, index, temp, 0, length);
                Array.Copy(array, 0, array, length, index);
                Array.Copy(temp, array, length);
            }
            ulong count = 0;
            int max = array[0];
            int maxCount = array.Count(item => item == max);
            Stack<int> stack = new Stack<int>();
            Dictionary<int, int> itemCount = new Dictionary<int, int>();
            for (int i = 1; i < n; ++i) {
                int current = array[i];
                if (current == max) {
                    stack.Clear();
                }
                else {
                    while (stack.Count>0 && stack.Peek() < current) {
                        int popped = stack.Pop();
                        itemCount[popped] = 0;
                        ++count;
                    }
                    if (stack.Count>0) {
                        if (stack.Peek() == current) {
                            int currentCount = itemCount[current];
                            count += (ulong)(currentCount + Math.Sign(stack.Count - currentCount));
                            ++itemCount[current];
                        }
                        else {
                            itemCount[current] = 1;
                            ++count;
                        }
                    }
                    stack.Push(current);
                    if (!itemCount.ContainsKey(current))
                        itemCount[current] = 1;
                }
            }
            int highest = int.MinValue;
            int lastMax = 0;
            for (int i = 1; i < n; ++i) {
                int current = array[i];
                if (current == max) {
                    highest = int.MinValue;
                    for (int j = i - 1; j > lastMax; --j) {
                        if (array[j] >= highest) {
                            highest = array[j];
                            ++count;
                        }
                    }
                    lastMax = i;
                    highest = int.MinValue;
                }
                else if (current >= highest) {
                    highest = current;
                    ++count;
                }
            }
            highest = int.MinValue;
            if (lastMax != 0) {
                for (int i = n - 1; i > lastMax; --i) {
                    if (array[i] >= highest) {
                        highest = array[i];
                        ++count;
                    }
                }
            }
            count += ((ulong)maxCount * (ulong)(maxCount - 1)) >> 1;
            Console.WriteLine(count);
        }

        public static int[] ReadIntArray() {
            return Console.ReadLine().Split(' ').Select(x => int.Parse(x)).ToArray();
        }

        public static int ReadInt() {
            return int.Parse(Console.ReadLine());
        }
    }

    public static class Extensions {
        public static string Fill(this char c, int count) {
            char[] r = new char[count];
            for (int i = 0; i < count; ++i)
                r[i] = c;
            return new string(r);
        }

        public static int MaxIntIndex(this int[] array) {
            int max = array[0];
            int index = 0;
            for (int i = 1; i < array.Length; ++i) {
                if (array[i] > max) {
                    max = array[i];
                    index = i;
                }
            }
            return index;
        }

        public static void PrintToConsole<T>(this IEnumerable<T> arr) {
            foreach (T t in arr)
                Console.Write("{0} ", t);
        }
    }
}


using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.IO;

namespace CodeForces {
    class Cf {
        static void Main(string[] args) {
            SolveC5E();
            //Console.ReadLine();
        }

        static void SolveC5E() {
            int n = ReadInt();
            int[] array = ReadIntArray();
            int index = array.MaxIntIndex();
            if (index > 0) {
                int length = n - index;
                int[] temp = new int[length];
                Array.Copy(array, index, temp, 0, length);
                Array.Copy(array, 0, array, length, index);
                Array.Copy(temp, array, length);
            }
            int count = 0;
            int max = array[0];
            Stack<int> stack = new Stack<int>();
            stack.Push(array[0]);
            Dictionary<int, int> itemCount = new Dictionary<int, int>();
            itemCount[max] = 1;
            for (int i = 1; i < n; ++i) {
                int current = array[i];
                while (stack.Peek() < current) {
                    int popped = stack.Pop();
                    itemCount[popped] = 0;
                    ++count;
                }
                if (stack.Peek() == current) {
                    int currentCount = itemCount[current];
                    count += currentCount + Math.Sign(stack.Count - currentCount);
                    ++itemCount[current];
                }
                else {
                    itemCount[current] = 1;
                    ++count;
                }
                stack.Push(current);
            }
            Console.WriteLine(count);
        }

        public static int[] ReadIntArray() {
            return Console.ReadLine().Split(' ').Select(x => int.Parse(x)).ToArray();
        }

        public static int ReadInt() {
            return int.Parse(Console.ReadLine());
        }
    }

    public static class Extensions {
        public static string Fill(this char c, int count) {
            char[] r = new char[count];
            for (int i = 0; i < count; ++i)
                r[i] = c;
            return new string(r);
        }

        public static int MaxIntIndex(this int[] array) {
            int max = array[0];
            int index = 0;
            for (int i = 1; i < array.Length; ++i) {
                if (array[i] > max) {
                    max = array[i];
                    index = i;
                }
            }
            return index;
        }

        public static void PrintToConsole<T>(this IEnumerable<T> arr) {
            foreach (T t in arr)
                Console.Write("{0} ", t);
        }
    }
}


using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.IO;

namespace CodeForces {
    class Cf {
        static void Main(string[] args) {
            SolveC5E();
            //Console.ReadLine();
        }

        static void SolveC5E() {
            int n = ReadInt();
            int[] array = ReadIntArray();
            int index = array.MaxIntIndex();
            if (index > 0) {
                int length = n - index;
                int[] temp = new int[length];
                Array.Copy(array, index, temp, 0, length);
                Array.Copy(array, 0, array, length, index);
                Array.Copy(temp, array, length);
            }
            int count = 0;
            int max = array[0];
            Stack<int> stack = new Stack<int>();
            stack.Push(array[0]);
            for (int i = 1; i < n; ++i) {
                int current = array[i];
                if (stack.Peek() >= current) {
                    stack.Push(current);
                }
                else {
                    int temp = 0;
                    while (stack.Peek() < current) {
                        stack.Pop();
                        ++temp;
                    }
                    if (temp > 1 && ((stack.Peek() != max) || (stack.Peek()==max && stack.Count>1)))
                        ++temp;
                    stack.Push(current);
                    count += temp;
                }
            }
            Console.WriteLine(count + n - 1);
        }

        public static int[] ReadIntArray() {
            return Console.ReadLine().Split(' ').Select(x => int.Parse(x)).ToArray();
        }

        public static int ReadInt() {
            return int.Parse(Console.ReadLine());
        }
    }

    public static class Extensions {
        public static string Fill(this char c, int count) {
            char[] r = new char[count];
            for (int i = 0; i < count; ++i)
                r[i] = c;
            return new string(r);
        }

        public static int MaxIntIndex(this int[] array) {
            int max = array[0];
            int index = 0;
            for (int i = 1; i < array.Length; ++i) {
                if (array[i] > max) {
                    max = array[i];
                    index = i;
                }
            }
            return index;
        }

        public static void PrintToConsole<T>(this IEnumerable<T> arr) {
            foreach (T t in arr)
                Console.Write("{0} ", t);
        }
    }
}


using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.IO;

namespace CodeForces {
    class Cf {
        static void Main(string[] args) {
            SolveC5E();
            //Console.ReadLine();
        }

        static void SolveC5E() {
            int n = ReadInt();
            int[] array = ReadIntArray();
            int index = array.MaxIntIndex();
            if (index > 0) {
                int length = n - index;
                int[] temp = new int[length];
                Array.Copy(array, index, temp, 0, length);
                Array.Copy(array, 0, array, length, index);
                Array.Copy(temp, array, length);
            }
            ulong count = 0;
            int max = array[0];
            int maxCount = array.Count(item => item == max);
            Stack<int> stack = new Stack<int>();
            Dictionary<int, int> itemCount = new Dictionary<int, int>();
            for (int i = 1; i < n; ++i) {
                int current = array[i];
                if (current == max) {
                    stack.Clear();
                }
                else {
                    while (stack.Count>0 && stack.Peek() < current) {
                        int popped = stack.Pop();
                        itemCount[popped] = 0;
                        ++count;
                    }
                    if (stack.Count>0) {
                        if (stack.Peek() == current) {
                            int currentCount = itemCount[current];
                            count += (ulong)(currentCount + Math.Sign(stack.Count - currentCount));
                            ++itemCount[current];
                        }
                        else {
                            itemCount[current] = 1;
                            ++count;
                        }
                    }
                    stack.Push(current);
                    if (!itemCount.ContainsKey(current))
                        itemCount[current] = 1;
                }
            }
            int highest = int.MinValue;
            int lastMax = 0;
            for (int i = 1; i < n; ++i) {
                int current = array[i];
                if (current == max) {
                    highest = int.MinValue;
                    for (int j = i - 1; j > lastMax; --j) {
                        if (array[j] >= highest) {
                            highest = array[j];
                            ++count;
                        }
                    }
                    lastMax = i;
                }
                else if (current >= highest) {
                    highest = current;
                    ++count;
                }
            }
            highest = int.MinValue;
            if (lastMax != 0) {
                for (int i = n - 1; i > lastMax; --i) {
                    if (array[i] >= highest) {
                        highest = array[i];
                        ++count;
                    }
                }
            }
            count += ((ulong)maxCount * (ulong)(maxCount - 1)) >> 1;
            Console.WriteLine(count);
        }

        public static int[] ReadIntArray() {
            return Console.ReadLine().Split(' ').Select(x => int.Parse(x)).ToArray();
        }

        public static int ReadInt() {
            return int.Parse(Console.ReadLine());
        }
    }

    public static class Extensions {
        public static string Fill(this char c, int count) {
            char[] r = new char[count];
            for (int i = 0; i < count; ++i)
                r[i] = c;
            return new string(r);
        }

        public static int MaxIntIndex(this int[] array) {
            int max = array[0];
            int index = 0;
            for (int i = 1; i < array.Length; ++i) {
                if (array[i] > max) {
                    max = array[i];
                    index = i;
                }
            }
            return index;
        }

        public static void PrintToConsole<T>(this IEnumerable<T> arr) {
            foreach (T t in arr)
                Console.Write("{0} ", t);
        }
    }
}


using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.IO;

namespace CodeForces {
    class Cf {
        static void Main(string[] args) {
            SolveC5E();
            //Console.ReadLine();
        }

        static void SolveC5E() {
            int n = ReadInt();
            int[] array = ReadIntArray();
            int index = array.MaxIntIndex();
            if (index > 0) {
                int length = n - index;
                int[] temp = new int[length];
                Array.Copy(array, index, temp, 0, length);
                Array.Copy(array, 0, array, length, index);
                Array.Copy(temp, array, length);
            }
            ulong count = 0;
            int max = array[0];
            int maxCount = array.Count(item => item == max);
            Stack<int> stack = new Stack<int>();
            Dictionary<int, int> itemCount = new Dictionary<int, int>();
            for (int i = 1; i < n; ++i) {
                int current = array[i];
                if (current == max) {
                    stack.Clear();
                }
                else {
                    while (stack.Count > 0 && stack.Peek() < current) {
                        int popped = stack.Pop();
                        count += (ulong)itemCount[popped];
                        itemCount[popped] = 0;
                    }
                    if (stack.Count > 0 && stack.Peek() == current) {
                        int currentCount = itemCount[current];
                        count += (ulong)currentCount;
                        if (stack.Count > 1)
                            ++count;
                        ++itemCount[current];
                    }
                    else {
                        if (stack.Count > 0)
                            ++count;
                        stack.Push(current);
                        itemCount[current] = 1;
                    }
                }
            }
            int highest = int.MinValue;
            int lastMax = 0;
            for (int i = 1; i < n; ++i) {
                int current = array[i];
                if (current == max) {
                    highest = int.MinValue;
                    for (int j = i - 1; j > lastMax; --j) {
                        if (array[j] >= highest) {
                            highest = array[j];
                            ++count;
                        }
                    }
                    lastMax = i;
                    highest = int.MinValue;
                }
                else if (current >= highest) {
                    highest = current;
                    ++count;
                }
            }
            highest = int.MinValue;
            if (lastMax != 0) {
                for (int i = n - 1; i > lastMax; --i) {
                    if (array[i] >= highest) {
                        highest = array[i];
                        ++count;
                    }
                }
            }
            count += ((ulong)maxCount * (ulong)(maxCount - 1)) >> 1;
            Console.WriteLine(count);
        }

        public static int[] ReadIntArray() {
            return Console.ReadLine().Split(' ').Select(x => int.Parse(x)).ToArray();
        }

        public static int ReadInt() {
            return int.Parse(Console.ReadLine());
        }
    }

    public static class Extensions {
        public static string Fill(this char c, int count) {
            char[] r = new char[count];
            for (int i = 0; i < count; ++i)
                r[i] = c;
            return new string(r);
        }

        public static int MaxIntIndex(this int[] array) {
            int max = array[0];
            int index = 0;
            for (int i = 1; i < array.Length; ++i) {
                if (array[i] > max) {
                    max = array[i];
                    index = i;
                }
            }
            return index;
        }

        public static void PrintToConsole<T>(this IEnumerable<T> arr) {
            foreach (T t in arr)
                Console.Write("{0} ", t);
        }
    }
}


using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.IO;

namespace CodeForces {
	class Cf {
		static void Main(string[] args) {
			SolveC5E();
			//Console.ReadLine();
		}

		static void SolveC5E() {
			int n = ReadInt();
			int[] array = ReadIntArray();
			int index = array.MaxIntIndex();
			if (index > 0) {
				int length = n - index;
				int[] temp = new int[length];
				Array.Copy(array, index, temp, 0, length);
				Array.Copy(array, 0, array, length, index);
				Array.Copy(temp, array, length);
			}
			ulong count = 0;
			int max = array[0];
			int maxCount = array.Count(item => item == max);
			Stack<int> stack = new Stack<int>();
			Dictionary<int, int> itemCount = new Dictionary<int, int>();
			for (int i = 1; i < n; ++i) {
				int current = array[i];
				if (current == max) {
					stack.Clear();
				}
				else {
					while (stack.Count > 0 && stack.Peek() < current) {
						int popped = stack.Pop();
						count += (ulong)itemCount[popped];
						itemCount[popped] = 0;
					}
					if (stack.Count > 0 && stack.Peek() == current) {
						int currentCount = itemCount[current];
						count += (ulong)currentCount;
						if (stack.Count > 1)
							++count;
						++itemCount[current];
					}
					else {
						if (stack.Count > 0)
							++count;
						stack.Push(current);
						itemCount[current] = 1;
					}
				}
			}
			int highest = int.MinValue;
			int lastMax = 0;
			int highest0index = 0;
			for (int i = 1; i < n; ++i) {
				int current = array[i];
				if (current == max) {
					highest = int.MinValue;
					for (int j = i - 1; j > lastMax; --j) {
						if (array[j] >= highest) {
							highest = array[j];
							++count;
						}
					}
					lastMax = i;
					highest = int.MinValue;
				}
				else if (current >= highest) {
					if (lastMax == 0)
						highest0index = i;
					highest = current;
					++count;
				}
			}
			highest = int.MinValue;
			for (int i = n - 1; i > lastMax; --i) {
				if (i == highest0index) break;
				if (array[i] >= highest) {
					highest = array[i];
					++count;
				}
			}
			count += ((ulong)maxCount * (ulong)(maxCount - 1)) >> 1;
			Console.WriteLine(count);
		}

		public static int[] ReadIntArray() {
			return Console.ReadLine().Split(' ').Select(x => int.Parse(x)).ToArray();
		}

		public static int ReadInt() {
			return int.Parse(Console.ReadLine());
		}
	}

	public static class Extensions {
		public static string Fill(this char c, int count) {
			char[] r = new char[count];
			for (int i = 0; i < count; ++i)
				r[i] = c;
			return new string(r);
		}

		public static int MaxIntIndex(this int[] array) {
			int max = array[0];
			int index = 0;
			for (int i = 1; i < array.Length; ++i) {
				if (array[i] > max) {
					max = array[i];
					index = i;
				}
			}
			return index;
		}

		public static void PrintToConsole<T>(this IEnumerable<T> arr) {
			foreach (T t in arr)
				Console.Write("{0} ", t);
		}
	}
}


use std::io::{self, Read as _};

fn main() {
    let mut input = String::new();
    io::stdin().read_to_string(&mut input).unwrap();
    let mut input = input.split_whitespace();
    macro_rules! read(
        ([$tt:tt]) => (read!([$tt; read!(usize)]));
        ([$tt:tt; $n:expr]) => ((0..$n).map(|_| read!($tt)).collect::<Vec<_>>());
        ($ty:ty) => (input.next().unwrap().parse::<$ty>().unwrap());
    );

    let n = read!(usize);
    let mut hs = read!([u64; n]);

    let max = *hs.iter().max().unwrap();
    let i = hs.iter().position(|&h| h == max).unwrap();
    let xs = hs
        .iter()
        .skip(i)
        .chain(hs.iter().take(i))
        .map(|&x| x)
        .collect::<Vec<u64>>();
    let mut vs = vec![0; n];
    let mut ans = 0;
    let mut i = 0;
    for &h in &xs {
        let mut v = 1;
        while i > 0 && h >= hs[i - 1] {
            i -= 1;
            ans += vs[i];
            if h == hs[i] {
                v += vs[i];
            }
        }
        if i > 0 {
            ans += 1;
        }
        vs[i] = v;
        hs[i] = h;
        i += 1;
    }
    ans += vs
        .iter()
        .take(i)
        .skip(if vs[0] == 1 { 2 } else { 1 })
        .sum::<u64>();

    println!("{:?}", ans);
}


package main

import (
	"bytes"
	"fmt"
	"io/ioutil"
	"os"
	"sort"
)

type Node struct {
	value int
	count int64
}

func reverse(a []int) {
	for i := 0; ; i++ {
		j := len(a) - i - 1
		if i >= j {
			return
		}
		a[i], a[j] = a[j], a[i]
	}
}

func main() {
	bs, _ := ioutil.ReadAll(os.Stdin)
	reader := bytes.NewBuffer(bs)
	var n int

	fmt.Fscanf(reader, "%d\n", &n)
	number := make([]int, 0, 1000000)
	sorted := make([]int, 0, 1000000)
	stack := make([]*Node, 1000000, 1000000)
	var pointer int
	for i := 0; i < n; i++ {
		var hill int
		fmt.Fscanf(reader, "%d ", &hill)
		number = append(number, hill)
		sorted = append(sorted, hill)
	}

	sort.Ints(sorted)
	max := sorted[n-1]
	prev, pos := max, n

	result := int64(0)
	maxPos := 0
	for i := n - 1; i >= 0; i-- {
		if sorted[i] != prev {
			pos = i + 1
			prev = sorted[i]
		}
		inc := n - pos
		if inc >= 2 {
			result += 2
		} else {
			result += int64(inc)
		}
		if number[i] == max {
			maxPos = i
		}
	}
	reverse(number[:maxPos+1])
	reverse(number[maxPos+1:])
	reverse(number)

	for i := 0; i < len(number); i++ {
		for pointer != 0 {
			if stack[pointer-1].value == number[i] {
				stack[pointer-1].count++
				break
			} else if stack[pointer-1].value > number[i] {
				stack[pointer] = &Node{number[i], 1}
				pointer++
				break
			} else {
				count := stack[pointer-1].count
				result = result + (count * (count - 1) / 2)
				pointer--
			}
		}
		if pointer == 0 {
			stack[pointer] = &Node{number[i], 1}
			pointer++
		}
	}

	for pointer != 0 {
		count := stack[pointer-1].count
		result = result + (count * (count - 1) / 2)
		pointer--
	}

	fmt.Printf("%d", result)

}