You are given a string $s$. You have to reverse it — that is, the first letter should become equal to the last letter before the reversal, the second letter should become equal to the second-to-last letter before the reversal — and so on. For example, if your goal is to reverse the string "abddea", you should get the string "aeddba". To accomplish your goal, you can swap the neighboring elements of the string. 

Your task is to calculate the minimum number of swaps you have to perform to reverse the given string.


-----Input-----

The first line contains one integer $n$ ($2 \le n \le 200\,000$) — the length of $s$.

The second line contains $s$ — a string consisting of $n$ lowercase Latin letters.


-----Output-----

Print one integer — the minimum number of swaps of neighboring elements you have to perform to reverse the string.


-----Examples-----
Input
5
aaaza

Output
2

Input
6
cbaabc

Output
0

Input
9
icpcsguru

Output
30



-----Note-----

In the first example, you have to swap the third and the fourth elements, so the string becomes "aazaa". Then you have to swap the second and the third elements, so the string becomes "azaaa". So, it is possible to reverse the string in two swaps.

Since the string in the second example is a palindrome, you don't have to do anything to reverse it.

Difficulty: HARD
Tags: String algorithms

Data structures

Greedy algorithms
Skill types: Data structures

Greedy algorithms

Starter code:

Solutions:
def mergeSort(arr, n):
	temp_arr = [0] * n
	return _mergeSort(arr, temp_arr, 0, n - 1)

def _mergeSort(arr, temp_arr, left, right):
	inv_count = 0
	if left < right:
		mid = (left + right) // 2
		inv_count += _mergeSort(arr, temp_arr, left, mid)
		inv_count += _mergeSort(arr, temp_arr, mid + 1, right)
		inv_count += merge(arr, temp_arr, left, mid, right)
	return inv_count

def merge(arr, temp_arr, left, mid, right):
	i = left
	j = mid + 1
	k = left
	inv_count = 0
	while i <= mid and j <= right:
		if arr[i] <= arr[j]:
			temp_arr[k] = arr[i]
			k += 1
			i += 1
		else:
			temp_arr[k] = arr[j]
			inv_count += mid - i + 1
			k += 1
			j += 1
	while i <= mid:
		temp_arr[k] = arr[i]
		k += 1
		i += 1
	while j <= right:
		temp_arr[k] = arr[j]
		k += 1
		j += 1
	for loop_var in range(left, right + 1):
		arr[loop_var] = temp_arr[loop_var]
	return inv_count
a = int(input())
z = input()
from collections import *
al = defaultdict(list)
for i in range(len(z)):
	al[z[i]].append(i)
for i in al:
	al[i] = al[i][::-1]
z = z[::-1]
ans = []
for i in range(len(z)):
	ans.append(al[z[i]][-1])
	al[z[i]].pop()
n = len(ans)
result = mergeSort(ans, n)
print(result)


import heapq
import collections
from math import log2
import itertools
from functools import lru_cache
from sys import setrecursionlimit as srl
srl(2 * 10 ** 6)
N = 200001

class fenwick:

	def __init__(self, n):
		self.n = n
		self.arr = [0] * (n + 1)

	def update(self, ind, x):
		if ind <= 0:
			return
		while ind <= self.n:
			self.arr[ind] += x
			ind += ind & -ind

	def query(self, ind):
		s = 0
		while ind > 0:
			s += self.arr[ind]
			ind -= ind & -ind
		return s

def solve(n, s):
	fen = fenwick(n + 1)
	inv = 0
	t = s[::-1]
	chars = collections.defaultdict(collections.deque)
	for i in range(n):
		chars[ord(s[i]) - ord('a')].append(i)
	for i in range(n):
		v = chars[ord(t[i]) - ord('a')].popleft()
		fen.update(v + 1, 1)
		v += i + 1 - fen.query(v + 1)
		inv += v - i
	return inv
n = int(input())
s = input()
print(solve(n, s))


class BIT:

	def __init__(self, n):
		self.BIT = [0] * (n + 1)
		self.num = n

	def query(self, idx):
		res_sum = 0
		while idx > 0:
			res_sum += self.BIT[idx]
			idx -= idx & -idx
		return res_sum

	def update(self, idx, x):
		while idx <= self.num:
			self.BIT[idx] += x
			idx += idx & -idx
		return
al = [chr(97 + i) for i in range(26)]
n = int(input())
s = input()
s = [s[i] for i in range(n)]
goal = s[::-1]
dic = {a: [] for a in al}
for i in range(n):
	dic[goal[i]].append(i)
for a in dic:
	dic[a] = dic[a][::-1]
seq = [-1 for i in range(n)]
for i in range(n):
	seq[i] = dic[s[i]].pop() + 1
res = 0
bit = BIT(n)
for i in range(n):
	res += i - bit.query(seq[i])
	bit.update(seq[i], 1)
print(res)


import os
import sys
from io import BytesIO, IOBase
BUFSIZE = 8192

class FastIO(IOBase):
	newlines = 0

	def __init__(self, file):
		self._fd = file.fileno()
		self.buffer = BytesIO()
		self.writable = 'x' in file.mode or 'r' not in file.mode
		self.write = self.buffer.write if self.writable else None

	def read(self):
		while True:
			b = os.read(self._fd, max(os.fstat(self._fd).st_size, BUFSIZE))
			if not b:
				break
			ptr = self.buffer.tell()
			(self.buffer.seek(0, 2), self.buffer.write(b), self.buffer.seek(ptr))
		self.newlines = 0
		return self.buffer.read()

	def readline(self):
		while self.newlines == 0:
			b = os.read(self._fd, max(os.fstat(self._fd).st_size, BUFSIZE))
			self.newlines = b.count(b'\n') + (not b)
			ptr = self.buffer.tell()
			(self.buffer.seek(0, 2), self.buffer.write(b), self.buffer.seek(ptr))
		self.newlines -= 1
		return self.buffer.readline()

	def flush(self):
		if self.writable:
			os.write(self._fd, self.buffer.getvalue())
			(self.buffer.truncate(0), self.buffer.seek(0))

class IOWrapper(IOBase):

	def __init__(self, file):
		self.buffer = FastIO(file)
		self.flush = self.buffer.flush
		self.writable = self.buffer.writable
		self.write = lambda s: self.buffer.write(s.encode('ascii'))
		self.read = lambda : self.buffer.read().decode('ascii')
		self.readline = lambda : self.buffer.readline().decode('ascii')
(sys.stdin, sys.stdout) = (IOWrapper(sys.stdin), IOWrapper(sys.stdout))
input = lambda : sys.stdin.readline().rstrip('\r\n')
import math
import bisect
from collections import Counter
import bisect
n = int(input())
from collections import defaultdict
s = input()
t = s[::-1]
d = defaultdict(lambda : [])
for (ind, val) in enumerate(t):
	d[val].append(ind)
for i in d.keys():
	d[i].reverse()
arr = []
bit = [0] * (n + 1)
for c in s:
	arr.append(d[c].pop())

def bit_sum(ind):
	val = 0
	while ind > 0:
		val += bit[ind]
		ind -= ind & -ind
	return val

def bit_up(ind, w):
	while ind <= n:
		bit[ind] += w
		ind += ind & -ind
inv = 0
for val in reversed(arr):
	inv += bit_sum(val + 1)
	bit_up(val + 1, 1)
print(inv)


from collections import defaultdict
n = int(input())
S = list(input())
C = defaultdict(list)
I = defaultdict(int)
for (i, c) in enumerate(S):
	C[c].append(i)
up = 0
SR = S[::-1]

def brute():
	swa = 0
	for i in range(n):
		if S[i] == SR[i]:
			continue
		c = SR[i]
		j = S.index(c, i)
		swa += j - i
		S[i:i] = S.pop(j)
	return swa
s = [0] * n

def update(pos, dif):
	while pos < n:
		s[pos] += dif
		pos |= pos + 1

def query(pos):
	res = 0
	while pos > 0:
		res += s[pos - 1]
		pos &= pos - 1
	return res
p = 0
swa = 0
for (i, c) in enumerate(SR):
	L = C[c]
	j = I[c]
	at = up + L[j] + query(L[j])
	assert at >= i
	if up + L[j] > i:
		swa += at - i
	update(L[j], -1)
	up += 1
	I[c] += 1
print(swa)


from collections import deque
n = int(input())
k = input()
s = []
for i in k:
	if i != '\x00':
		s.append(i)
d = {}
for i in range(n - 1, -1, -1):
	if s[i] in d:
		d[s[i]].append(n - i - 1)
	else:
		d[s[i]] = deque([n - i - 1])
lis = [-1] * n
for i in range(n):
	lis[i] = d[s[i]].popleft()

def merge(a, b):
	(i, j, ans) = (0, 0, 0)
	(n, m) = (len(a), len(b))
	c = []
	while i < n and j < m:
		if a[i] <= b[j]:
			c.append(a[i])
			i += 1
		else:
			c.append(b[j])
			j += 1
			ans += n - i
	while i < n:
		c.append(a[i])
		i += 1
	while j < m:
		c.append(b[j])
		j += 1
	return (c, ans)

def mergesort(lis):
	p = len(lis)
	if p in (0, 1):
		return (lis, 0)
	mid = p // 2
	(a, v1) = mergesort(lis[:mid])
	(b, v2) = mergesort(lis[mid:])
	(c, v3) = merge(a, b)
	return (c, v1 + v2 + v3)
(_, ans) = mergesort(lis)
print(ans)


from pprint import pprint

def do():

	def gindex(l, r):
		L = l + N0 >> 1
		R = r + N0 >> 1
		lc = 0 if l & 1 else (L & -L).bit_length()
		rc = 0 if r & 1 else (R & -R).bit_length()
		for i in range(LV):
			if rc <= i:
				yield R
			if L < R and lc <= i:
				yield L
			L >>= 1
			R >>= 1

	def propagates(*ids):
		for i in reversed(ids):
			v = lazy[i - 1]
			if v is None:
				continue
			lazy[2 * i - 1] = lazy[2 * i] = data[2 * i - 1] = data[2 * i] = v >> 1
			lazy[i - 1] = None

	def update(l, r, x):
		(*ids,) = gindex(l, r)
		propagates(*ids)
		L = N0 + l
		R = N0 + r
		v = x
		while L < R:
			if R & 1:
				R -= 1
				lazy[R - 1] = data[R - 1] = v
			if L & 1:
				lazy[L - 1] = data[L - 1] = v
				L += 1
			L >>= 1
			R >>= 1
			v <<= 1
		for i in ids:
			data[i - 1] = data[2 * i - 1] + data[2 * i]

	def query(l, r):
		propagates(*gindex(l, r))
		L = N0 + l
		R = N0 + r
		s = 0
		while L < R:
			if R & 1:
				R -= 1
				s += data[R - 1]
			if L & 1:
				s += data[L - 1]
				L += 1
			L >>= 1
			R >>= 1
		return s
	charpos = []
	for i in range(26):
		charpos.append([])
	charused = [0] * 26
	n = int(input())
	s = input()
	N = n
	LV = (N - 1).bit_length()
	N0 = 2 ** LV
	data = [0] * (2 * N0)
	lazy = [None] * (2 * N0)
	targets = s[::-1]
	s = list(s)
	for i in range(n):
		x = ord(s[i]) - ord('a')
		charpos[x].append(i)
	res = 0
	for i in range(n):
		tx = ord(targets[i]) - ord('a')
		used = charused[tx]
		originalpos = charpos[tx][used]
		update(originalpos, originalpos + 1, 1)
		charused[tx] += 1
		originalpos += query(originalpos + 1, n)
		d = originalpos - i
		if d > 0:
			res += d
	print(res)
do()


import math
import random
import heapq, bisect
import sys
from collections import deque, defaultdict
from fractions import Fraction
import sys
import threading
from collections import defaultdict
mod = 10 ** 9 + 7
mod1 = 998244353
import os
import sys
from io import BytesIO, IOBase
BUFSIZE = 8192

class FastIO(IOBase):
	newlines = 0

	def __init__(self, file):
		self._fd = file.fileno()
		self.buffer = BytesIO()
		self.writable = 'x' in file.mode or 'r' not in file.mode
		self.write = self.buffer.write if self.writable else None

	def read(self):
		while True:
			b = os.read(self._fd, max(os.fstat(self._fd).st_size, BUFSIZE))
			if not b:
				break
			ptr = self.buffer.tell()
			(self.buffer.seek(0, 2), self.buffer.write(b), self.buffer.seek(ptr))
		self.newlines = 0
		return self.buffer.read()

	def readline(self):
		while self.newlines == 0:
			b = os.read(self._fd, max(os.fstat(self._fd).st_size, BUFSIZE))
			self.newlines = b.count(b'\n') + (not b)
			ptr = self.buffer.tell()
			(self.buffer.seek(0, 2), self.buffer.write(b), self.buffer.seek(ptr))
		self.newlines -= 1
		return self.buffer.readline()

	def flush(self):
		if self.writable:
			os.write(self._fd, self.buffer.getvalue())
			(self.buffer.truncate(0), self.buffer.seek(0))

class IOWrapper(IOBase):

	def __init__(self, file):
		self.buffer = FastIO(file)
		self.flush = self.buffer.flush
		self.writable = self.buffer.writable
		self.write = lambda s: self.buffer.write(s.encode('ascii'))
		self.read = lambda : self.buffer.read().decode('ascii')
		self.readline = lambda : self.buffer.readline().decode('ascii')
(sys.stdin, sys.stdout) = (IOWrapper(sys.stdin), IOWrapper(sys.stdout))
input = lambda : sys.stdin.readline().rstrip('\r\n')

class TreeNode:

	def __init__(self, k, v):
		self.key = k
		self.value = v
		self.left = None
		self.right = None
		self.parent = None
		self.height = 1
		self.num_left = 1
		self.num_total = 1

class AvlTree:

	def __init__(self):
		self._tree = None

	def add(self, k, v):
		if not self._tree:
			self._tree = TreeNode(k, v)
			return
		node = self._add(k, v)
		if node:
			self._rebalance(node)

	def _add(self, k, v):
		node = self._tree
		while node:
			if k < node.key:
				if node.left:
					node = node.left
				else:
					node.left = TreeNode(k, v)
					node.left.parent = node
					return node.left
			elif node.key < k:
				if node.right:
					node = node.right
				else:
					node.right = TreeNode(k, v)
					node.right.parent = node
					return node.right
			else:
				node.value = v
				return

	@staticmethod
	def get_height(x):
		return x.height if x else 0

	@staticmethod
	def get_num_total(x):
		return x.num_total if x else 0

	def _rebalance(self, node):
		n = node
		while n:
			lh = self.get_height(n.left)
			rh = self.get_height(n.right)
			n.height = max(lh, rh) + 1
			balance_factor = lh - rh
			n.num_total = 1 + self.get_num_total(n.left) + self.get_num_total(n.right)
			n.num_left = 1 + self.get_num_total(n.left)
			if balance_factor > 1:
				if self.get_height(n.left.left) < self.get_height(n.left.right):
					self._rotate_left(n.left)
				self._rotate_right(n)
			elif balance_factor < -1:
				if self.get_height(n.right.right) < self.get_height(n.right.left):
					self._rotate_right(n.right)
				self._rotate_left(n)
			else:
				n = n.parent

	def _remove_one(self, node):
		replacement = node.left or node.right
		if node.parent:
			if AvlTree._is_left(node):
				node.parent.left = replacement
			else:
				node.parent.right = replacement
			replacement.parent = node.parent
			node.parent = None
		else:
			self._tree = replacement
			replacement.parent = None
		node.left = None
		node.right = None
		node.parent = None
		self._rebalance(replacement)

	def _remove_leaf(self, node):
		if node.parent:
			if AvlTree._is_left(node):
				node.parent.left = None
			else:
				node.parent.right = None
			self._rebalance(node.parent)
		else:
			self._tree = None
		node.parent = None
		node.left = None
		node.right = None

	def remove(self, k):
		node = self._get_node(k)
		if not node:
			return
		if AvlTree._is_leaf(node):
			self._remove_leaf(node)
			return
		if node.left and node.right:
			nxt = AvlTree._get_next(node)
			node.key = nxt.key
			node.value = nxt.value
			if self._is_leaf(nxt):
				self._remove_leaf(nxt)
			else:
				self._remove_one(nxt)
			self._rebalance(node)
		else:
			self._remove_one(node)

	def get(self, k):
		node = self._get_node(k)
		return node.value if node else -1

	def _get_node(self, k):
		if not self._tree:
			return None
		node = self._tree
		while node:
			if k < node.key:
				node = node.left
			elif node.key < k:
				node = node.right
			else:
				return node
		return None

	def get_at(self, pos):
		x = pos + 1
		node = self._tree
		while node:
			if x < node.num_left:
				node = node.left
			elif node.num_left < x:
				x -= node.num_left
				node = node.right
			else:
				return (node.key, node.value)
		raise IndexError('Out of ranges')

	@staticmethod
	def _is_left(node):
		return node.parent.left and node.parent.left == node

	@staticmethod
	def _is_leaf(node):
		return node.left is None and node.right is None

	def _rotate_right(self, node):
		if not node.parent:
			self._tree = node.left
			node.left.parent = None
		elif AvlTree._is_left(node):
			node.parent.left = node.left
			node.left.parent = node.parent
		else:
			node.parent.right = node.left
			node.left.parent = node.parent
		bk = node.left.right
		node.left.right = node
		node.parent = node.left
		node.left = bk
		if bk:
			bk.parent = node
		node.height = max(self.get_height(node.left), self.get_height(node.right)) + 1
		node.num_total = 1 + self.get_num_total(node.left) + self.get_num_total(node.right)
		node.num_left = 1 + self.get_num_total(node.left)

	def _rotate_left(self, node):
		if not node.parent:
			self._tree = node.right
			node.right.parent = None
		elif AvlTree._is_left(node):
			node.parent.left = node.right
			node.right.parent = node.parent
		else:
			node.parent.right = node.right
			node.right.parent = node.parent
		bk = node.right.left
		node.right.left = node
		node.parent = node.right
		node.right = bk
		if bk:
			bk.parent = node
		node.height = max(self.get_height(node.left), self.get_height(node.right)) + 1
		node.num_total = 1 + self.get_num_total(node.left) + self.get_num_total(node.right)
		node.num_left = 1 + self.get_num_total(node.left)

	@staticmethod
	def _get_next(node):
		if not node.right:
			return node.parent
		n = node.right
		while n.left:
			n = n.left
		return n

class SegmentTree1:

	def __init__(self, data, default=300006, func=lambda a, b: min(a, b)):
		self._default = default
		self._func = func
		self._len = len(data)
		self._size = _size = 1 << (self._len - 1).bit_length()
		self.data = [default] * (2 * _size)
		self.data[_size:_size + self._len] = data
		for i in reversed(range(_size)):
			self.data[i] = func(self.data[i + i], self.data[i + i + 1])

	def __delitem__(self, idx):
		self[idx] = self._default

	def __getitem__(self, idx):
		return self.data[idx + self._size]

	def __setitem__(self, idx, value):
		idx += self._size
		self.data[idx] = value
		idx >>= 1
		while idx:
			self.data[idx] = self._func(self.data[2 * idx], self.data[2 * idx + 1])
			idx >>= 1

	def __len__(self):
		return self._len

	def query(self, start, stop):
		if start == stop:
			return self.__getitem__(start)
		stop += 1
		start += self._size
		stop += self._size
		res = self._default
		while start < stop:
			if start & 1:
				res = self._func(res, self.data[start])
				start += 1
			if stop & 1:
				stop -= 1
				res = self._func(res, self.data[stop])
			start >>= 1
			stop >>= 1
		return res

	def __repr__(self):
		return 'SegmentTree({0})'.format(self.data)

class SegmentTree:

	def __init__(self, data, default=0, func=lambda a, b: a + b):
		self._default = default
		self._func = func
		self._len = len(data)
		self._size = _size = 1 << (self._len - 1).bit_length()
		self.data = [default] * (2 * _size)
		self.data[_size:_size + self._len] = data
		for i in reversed(range(_size)):
			self.data[i] = func(self.data[i + i], self.data[i + i + 1])

	def __delitem__(self, idx):
		self[idx] = self._default

	def __getitem__(self, idx):
		return self.data[idx + self._size]

	def __setitem__(self, idx, value):
		idx += self._size
		self.data[idx] = value
		idx >>= 1
		while idx:
			self.data[idx] = self._func(self.data[2 * idx], self.data[2 * idx + 1])
			idx >>= 1

	def __len__(self):
		return self._len

	def query(self, start, stop):
		if start == stop:
			return self.__getitem__(start)
		stop += 1
		start += self._size
		stop += self._size
		res = self._default
		while start < stop:
			if start & 1:
				res = self._func(res, self.data[start])
				start += 1
			if stop & 1:
				stop -= 1
				res = self._func(res, self.data[stop])
			start >>= 1
			stop >>= 1
		return res

	def __repr__(self):
		return 'SegmentTree({0})'.format(self.data)

class Factorial:

	def __init__(self, MOD):
		self.MOD = MOD
		self.factorials = [1, 1]
		self.invModulos = [0, 1]
		self.invFactorial_ = [1, 1]

	def calc(self, n):
		if n <= -1:
			print('Invalid argument to calculate n!')
			print('n must be non-negative value. But the argument was ' + str(n))
			exit()
		if n < len(self.factorials):
			return self.factorials[n]
		nextArr = [0] * (n + 1 - len(self.factorials))
		initialI = len(self.factorials)
		prev = self.factorials[-1]
		m = self.MOD
		for i in range(initialI, n + 1):
			prev = nextArr[i - initialI] = prev * i % m
		self.factorials += nextArr
		return self.factorials[n]

	def inv(self, n):
		if n <= -1:
			print('Invalid argument to calculate n^(-1)')
			print('n must be non-negative value. But the argument was ' + str(n))
			exit()
		p = self.MOD
		pi = n % p
		if pi < len(self.invModulos):
			return self.invModulos[pi]
		nextArr = [0] * (n + 1 - len(self.invModulos))
		initialI = len(self.invModulos)
		for i in range(initialI, min(p, n + 1)):
			next = -self.invModulos[p % i] * (p // i) % p
			self.invModulos.append(next)
		return self.invModulos[pi]

	def invFactorial(self, n):
		if n <= -1:
			print('Invalid argument to calculate (n^(-1))!')
			print('n must be non-negative value. But the argument was ' + str(n))
			exit()
		if n < len(self.invFactorial_):
			return self.invFactorial_[n]
		self.inv(n)
		nextArr = [0] * (n + 1 - len(self.invFactorial_))
		initialI = len(self.invFactorial_)
		prev = self.invFactorial_[-1]
		p = self.MOD
		for i in range(initialI, n + 1):
			prev = nextArr[i - initialI] = prev * self.invModulos[i % p] % p
		self.invFactorial_ += nextArr
		return self.invFactorial_[n]

class Combination:

	def __init__(self, MOD):
		self.MOD = MOD
		self.factorial = Factorial(MOD)

	def ncr(self, n, k):
		if k < 0 or n < k:
			return 0
		k = min(k, n - k)
		f = self.factorial
		return f.calc(n) * f.invFactorial(max(n - k, k)) * f.invFactorial(min(k, n - k)) % self.MOD

def powm(a, n, m):
	if a == 1 or n == 0:
		return 1
	if n % 2 == 0:
		s = powm(a, n // 2, m)
		return s * s % m
	else:
		return a * powm(a, n - 1, m) % m

def sort_list(list1, list2):
	zipped_pairs = zip(list2, list1)
	z = [x for (_, x) in sorted(zipped_pairs)]
	return z

def product(l):
	por = 1
	for i in range(len(l)):
		por *= l[i]
	return por

def binarySearchCount(arr, n, key):
	left = 0
	right = n - 1
	count = 0
	while left <= right:
		mid = int((right + left) / 2)
		if arr[mid] <= key:
			count = mid + 1
			left = mid + 1
		else:
			right = mid - 1
	return count

def countdig(n):
	c = 0
	while n > 0:
		n //= 10
		c += 1
	return c

def binary(x, length):
	y = bin(x)[2:]
	return y if len(y) >= length else '0' * (length - len(y)) + y

def countGreater(arr, n, k):
	l = 0
	r = n - 1
	leftGreater = n
	while l <= r:
		m = int(l + (r - l) / 2)
		if arr[m] > k:
			leftGreater = m
			r = m - 1
		else:
			l = m + 1
	return n - leftGreater

class TrieNode:

	def __init__(self):
		self.children = [None] * 26
		self.isEndOfWord = False

class Trie:

	def __init__(self):
		self.root = self.getNode()

	def getNode(self):
		return TrieNode()

	def _charToIndex(self, ch):
		return ord(ch) - ord('a')

	def insert(self, key):
		pCrawl = self.root
		length = len(key)
		for level in range(length):
			index = self._charToIndex(key[level])
			if not pCrawl.children[index]:
				pCrawl.children[index] = self.getNode()
			pCrawl = pCrawl.children[index]
		pCrawl.isEndOfWord = True

	def search(self, key):
		pCrawl = self.root
		length = len(key)
		for level in range(length):
			index = self._charToIndex(key[level])
			if not pCrawl.children[index]:
				return False
			pCrawl = pCrawl.children[index]
		return pCrawl != None and pCrawl.isEndOfWord

class Node:

	def __init__(self, data):
		self.data = data
		self.count = 0
		self.left = None
		self.right = None

class BinaryTrie:

	def __init__(self):
		self.root = Node(0)

	def insert(self, pre_xor):
		self.temp = self.root
		for i in range(31, -1, -1):
			val = pre_xor & 1 << i
			if val:
				if not self.temp.right:
					self.temp.right = Node(0)
				self.temp = self.temp.right
				self.temp.count += 1
			if not val:
				if not self.temp.left:
					self.temp.left = Node(0)
				self.temp = self.temp.left
				self.temp.count += 1
		self.temp.data = pre_xor

	def query(self, xor):
		self.temp = self.root
		for i in range(31, -1, -1):
			val = xor & 1 << i
			if not val:
				if self.temp.left and self.temp.left.count > 0:
					self.temp = self.temp.left
				elif self.temp.right:
					self.temp = self.temp.right
			elif self.temp.right and self.temp.right.count > 0:
				self.temp = self.temp.right
			elif self.temp.left:
				self.temp = self.temp.left
			self.temp.count -= 1
		return xor ^ self.temp.data

def merge(arr, temp, left, mid, right):
	inv_count = 0
	i = left
	j = mid
	k = left
	while i <= mid - 1 and j <= right:
		if arr[i] <= arr[j]:
			temp[k] = arr[i]
			k += 1
			i += 1
		else:
			temp[k] = arr[j]
			k += 1
			j += 1
			inv_count = inv_count + (mid - i)
	while i <= mid - 1:
		temp[k] = arr[i]
		k += 1
		i += 1
	while j <= right:
		temp[k] = arr[j]
		k += 1
		j += 1
	for i in range(left, right + 1, 1):
		arr[i] = temp[i]
	return inv_count

def _mergeSort(arr, temp, left, right):
	inv_count = 0
	if right > left:
		mid = int((right + left) / 2)
		inv_count = _mergeSort(arr, temp, left, mid)
		inv_count += _mergeSort(arr, temp, mid + 1, right)
		inv_count += merge(arr, temp, left, mid + 1, right)
	return inv_count

def countSwaps(arr, n):
	temp = [0 for i in range(n)]
	return _mergeSort(arr, temp, 0, n - 1)
n = int(input())
s = input()
d = defaultdict(list)
t = defaultdict(int)
s = s[::-1]
for i in range(n):
	d[s[i]].append(i)
s = s[::-1]
l = []
for i in range(n):
	l.append(d[s[i]][t[s[i]]])
	t[s[i]] += 1
print(countSwaps(l, n))


from sys import stdin
input = lambda : stdin.readline().strip()
lin = lambda : list(map(int, input().split()))
iin = lambda : int(input())
main = lambda : map(int, input().split())
from math import ceil, sqrt, factorial, log
from collections import deque
from bisect import bisect_left
mod = 998244353
mod = 1000000007

def gcd(a, b):
	(a, b) = (max(a, b), min(a, b))
	while a % b != 0:
		(a, b) = (b, a % b)
	return b

def merge(arr, temp, left, mid, right):
	inv_count = 0
	i = left
	j = mid
	k = left
	while i <= mid - 1 and j <= right:
		if arr[i] <= arr[j]:
			temp[k] = arr[i]
			k += 1
			i += 1
		else:
			temp[k] = arr[j]
			k += 1
			j += 1
			inv_count = inv_count + (mid - i)
	while i <= mid - 1:
		temp[k] = arr[i]
		k += 1
		i += 1
	while j <= right:
		temp[k] = arr[j]
		k += 1
		j += 1
	for i in range(left, right + 1, 1):
		arr[i] = temp[i]
	return inv_count

def _mergeSort(arr, temp, left, right):
	inv_count = 0
	if right > left:
		mid = int((right + left) / 2)
		inv_count = _mergeSort(arr, temp, left, mid)
		inv_count += _mergeSort(arr, temp, mid + 1, right)
		inv_count += merge(arr, temp, left, mid + 1, right)
	return inv_count

def countSwaps(arr, n):
	temp = [0 for i in range(n)]
	return _mergeSort(arr, temp, 0, n - 1)

def moduloinverse(a):
	return pow(a, mod - 2, mod)

def solve(we):
	n = iin()
	s = input()
	d = {chr(i): deque() for i in range(97, 123)}
	for i in range(n):
		d[s[i]].append(i)
	j = n - 1
	z = [0 for i in range(n)]
	for i in range(n):
		z[i] = d[s[j]].popleft()
		j -= 1
	x = [0 for i in range(n)]
	for i in range(n):
		x[z[i]] = i + 1
	print(countSwaps(x, n))
qwe = 1
for _ in range(qwe):
	solve(_ + 1)


import sys
from collections import deque

def eprint(*args):
	print(*args, file=sys.stderr)
zz = 1
if zz:
	input = sys.stdin.readline
else:
	sys.stdin = open('input.txt', 'r')
	sys.stdout = open('all.txt', 'w')
di = [[-1, 0], [1, 0], [0, 1], [0, -1]]

def string(s):
	return ''.join(s)

def fori(n):
	return [fi() for i in range(n)]

def inc(d, c, x=1):
	d[c] = d[c] + x if c in d else x

def bo(i):
	return ord(i) - ord('A')

def li():
	return [int(xx) for xx in input().split()]

def fli():
	return [float(x) for x in input().split()]

def comp(a, b):
	if a > b:
		return 2
	return 2 if a == b else 0

def gi():
	return [xx for xx in input().split()]

def cil(n, m):
	return n // m + int(n % m > 0)

def fi():
	return int(input())

def pro(a):
	return reduce(lambda a, b: a * b, a)

def swap(a, i, j):
	(a[i], a[j]) = (a[j], a[i])

def si():
	return list(input().rstrip())

def mi():
	return map(int, input().split())

def gh():
	sys.stdout.flush()

def isvalid(i, j):
	return 0 <= i < n and 0 <= j < m and (a[i][j] != '.')

def bo(i):
	return ord(i) - ord('a')

def graph(n, m):
	for i in range(m):
		(x, y) = mi()
		a[x].append(y)
		a[y].append(x)

def update(pos, val):
	while pos <= 2 * n:
		d[pos] += val
		pos += pos & -pos

def ssum(pos):
	c = 0
	while pos > 0:
		c += d[pos]
		pos -= pos & -pos
	return c
t = 1
while t > 0:
	t -= 1
	n = fi()
	s = si()
	p = s[::-1]
	d = [0] * (2 * n + 2)
	ans = 0
	w = [deque() for i in range(27)]
	vis = {}
	mex = 0
	for i in range(n):
		w[bo(s[i])].append(i)
	for i in range(n):
		pp = ssum(mex + 1)
		if s[mex] != p[i]:
			z = w[bo(p[i])][0]
			w[bo(p[i])].popleft()
			ps = ssum(z + 1)
			ans += z + ps - mex - pp
			update(mex + 1, 1)
			update(z + 2, -1)
			vis[z] = 1
			while mex in vis:
				mex += 1
		else:
			z = w[bo(p[i])][0]
			vis[z] = 1
			while mex in vis:
				mex += 1
			w[bo(p[i])].popleft()
	print(ans)


import io
import os
from collections import Counter, defaultdict, deque

class SegmentTree:

	def __init__(self, data, default=0, func=max):
		self._default = default
		self._func = func
		self._len = len(data)
		self._size = _size = 1 << (self._len - 1).bit_length()
		self.data = [default] * (2 * _size)
		self.data[_size:_size + self._len] = data
		for i in reversed(range(_size)):
			self.data[i] = func(self.data[i + i], self.data[i + i + 1])

	def __delitem__(self, idx):
		self[idx] = self._default

	def __getitem__(self, idx):
		return self.data[idx + self._size]

	def __setitem__(self, idx, value):
		idx += self._size
		self.data[idx] = value
		idx >>= 1
		while idx:
			self.data[idx] = self._func(self.data[2 * idx], self.data[2 * idx + 1])
			idx >>= 1

	def __len__(self):
		return self._len

	def query(self, start, stop):
		start += self._size
		stop += self._size
		res_left = res_right = self._default
		while start < stop:
			if start & 1:
				res_left = self._func(res_left, self.data[start])
				start += 1
			if stop & 1:
				stop -= 1
				res_right = self._func(self.data[stop], res_right)
			start >>= 1
			stop >>= 1
		return self._func(res_left, res_right)

	def __repr__(self):
		return 'SegmentTree({0})'.format(self.data)

def solve(N, S):
	indices = defaultdict(deque)
	for (i, x) in enumerate(S):
		indices[x].append(i)
	segtree = SegmentTree([1] * N, 0, lambda x, y: x + y)
	ans = 0
	for (i, x) in enumerate(S[::-1]):
		index = indices[x].popleft()
		blocking = segtree.query(0, index)
		ans += blocking
		segtree[index] = 0
	return ans
input = io.BytesIO(os.read(0, os.fstat(0).st_size)).readline
(N,) = [int(x) for x in input().split()]
S = input().decode().rstrip()
ans = solve(N, S)
print(ans)


maxn = int(200000.0 + 5)
n = int(input())
s = input()
t = s[::-1]
a = [[] for i in range(31)]
tree = [0] * maxn
num = [0] * maxn
g = [0] * 30

def lowbit(x):
	return x & -x

def tadd(x, val):
	while x <= maxn:
		tree[x] += val
		x += lowbit(x)

def tsum(x):
	ans = 0
	while x > 0:
		ans += tree[x]
		x -= lowbit(x)
	return ans
for i in range(0, len(t)):
	ch = ord(t[i]) - ord('a')
	a[ch].append(i)
for i in range(0, len(s)):
	ch = ord(s[i]) - ord('a')
	num[i] = a[ch][g[ch]]
	g[ch] += 1
ans = 0
for i in range(0, len(s)):
	tadd(num[i] + 1, 1)
	ans += i + 1 - tsum(num[i] + 1)
print(ans)


import sys, math
import io, os
from bisect import bisect_left as bl, bisect_right as br, insort
from heapq import heapify, heappush, heappop
from collections import defaultdict as dd, deque, Counter

def data():
	return sys.stdin.readline().strip()

def mdata():
	return list(map(int, data().split()))

def outl(var):
	sys.stdout.write('\n'.join(map(str, var)) + '\n')

def out(var):
	sys.stdout.write(str(var) + '\n')
INF = float('inf')
mod = 10 ** 9 + 7

def construct(BIT, arr):
	for i in range(len(arr)):
		BIT[i + 1] = arr[i]

def updateBIT(BIT, v, w):
	while v <= n:
		BIT[v] += w
		v += v & -v

def getvalue(BIT, v):
	ANS = 0
	while v != 0:
		ANS += BIT[v]
		v -= v & -v
	return ANS

def bisect_on_BIT(BIT, x):
	if x <= 0:
		return 0
	ANS = 0
	h = 1 << n - 1
	while h > 0:
		if ANS + h <= n and BIT[ANS + h] < x:
			x -= BIT[ANS + h]
			ANS += h
		h //= 2
	return ANS + 1

def update(BIT, l, r, n, val):
	updateBIT(BIT, l, val)
	updateBIT(BIT, r + 1, -val)
n = int(data())
BIT = [0] * (n + 1)
s = data()
d = dd(list)
for i in range(n):
	d[s[i]].append(i)
for i in d:
	d[i] = d[i][::-1]
ans = 0
for i in s[::-1]:
	a = d[i].pop()
	ans += getvalue(BIT, n) - getvalue(BIT, a + 1)
	updateBIT(BIT, a + 1, 1)
out(ans)


from collections import defaultdict
import sys as _sys

def main():
	t = 1
	for i_t in range(t):
		(n,) = _read_ints()
		s = _read_line()
		result = find_min_moves_n_to_reverse(s)
		print(result)

def _read_line():
	result = _sys.stdin.readline()
	assert result[-1] == '\n'
	return result[:-1]

def _read_ints():
	return map(int, _read_line().split())

def find_min_moves_n_to_reverse(s):
	assert isinstance(s, str)
	reversed_s = s[::-1]
	indices_by_letters = defaultdict(list)
	for (i, letter) in enumerate(reversed_s):
		indices_by_letters[letter].append(i)
	indices_by_letters_rev = {letter: indices[::-1] for (letter, indices) in indices_by_letters.items()}
	necessary_indices = []
	for (i, letter) in enumerate(s):
		necessary_i = indices_by_letters_rev[letter].pop()
		necessary_indices.append(necessary_i)
	return _how_many_operations_for_bubble_sort(necessary_indices)

def _how_many_operations_for_bubble_sort(seq):
	max_element = max(seq)
	was_before_counter_ft = [0] * (max_element + 1 + 1)
	result = 0
	for (i_x, x) in enumerate(seq):
		result += _prefix_sum_fenwick(was_before_counter_ft, max_element) - _prefix_sum_fenwick(was_before_counter_ft, x)
		_add_fenwick(was_before_counter_ft, x, 1)
	return result

def _prefix_sum_fenwick(tree, i):
	i += 1
	result = 0
	while i:
		result += tree[i]
		i -= i & -i
	return result

def _add_fenwick(tree, i, x):
	i += 1
	while i < len(tree):
		tree[i] += x
		i += i & -i
main()


import os
import sys
from io import BytesIO, IOBase
_str = str
BUFSIZE = 8192

def str(x=b''):
	return x if type(x) is bytes else _str(x).encode()

class FastIO(IOBase):
	newlines = 0

	def __init__(self, file):
		self._fd = file.fileno()
		self.buffer = BytesIO()
		self.writable = 'x' in file.mode or 'r' not in file.mode
		self.write = self.buffer.write if self.writable else None

	def read(self):
		while True:
			b = os.read(self._fd, max(os.fstat(self._fd).st_size, BUFSIZE))
			if not b:
				break
			ptr = self.buffer.tell()
			(self.buffer.seek(0, 2), self.buffer.write(b), self.buffer.seek(ptr))
		self.newlines = 0
		return self.buffer.read()

	def readline(self):
		while self.newlines == 0:
			b = os.read(self._fd, max(os.fstat(self._fd).st_size, BUFSIZE))
			self.newlines = b.count(b'\n') + (not b)
			ptr = self.buffer.tell()
			(self.buffer.seek(0, 2), self.buffer.write(b), self.buffer.seek(ptr))
		self.newlines -= 1
		return self.buffer.readline()

	def flush(self):
		if self.writable:
			os.write(self._fd, self.buffer.getvalue())
			(self.buffer.truncate(0), self.buffer.seek(0))

class IOWrapper(IOBase):

	def __init__(self, file):
		self.buffer = FastIO(file)
		self.flush = self.buffer.flush
		self.writable = self.buffer.writable
		self.write = lambda s: self.buffer.write(s.encode('ascii'))
		self.read = lambda : self.buffer.read().decode('ascii')
		self.readline = lambda : self.buffer.readline().decode('ascii')

def inp():
	return sys.stdin.readline().rstrip()

def mpint():
	return map(int, sys.stdin.readline().split(' '))

def itg():
	return int(sys.stdin.readline())
from collections import defaultdict

def discretization(iterable):
	iterable = tuple(iterable)
	restore = sorted(set(iterable))
	return (list(map(dict(zip(restore, range(len(restore)))).__getitem__, iterable)), restore)

class Fenwick:

	def __init__(self, x):
		self.bit = [0] * x

	def update(self, idx, x):
		while idx < len(self.bit):
			self.bit[idx] += x
			idx |= idx + 1

	def query(self, end):
		x = 0
		while end:
			x += self.bit[end - 1]
			end &= end - 1
		return x

	def findkth(self, k):
		idx = -1
		for d in reversed(range(len(self.bit).bit_length())):
			right_idx = idx + (1 << d)
			if right_idx < len(self.bit) and k > self.bit[right_idx]:
				idx = right_idx
				k -= self.bit[idx]
		return idx + 1

def inversion(iterable):
	iterable = discretization(iterable)[0]
	index = len(iterable)
	bit = Fenwick(index)
	result = [0] * index
	for item in reversed(iterable):
		index -= 1
		result[index] = bit.query(item)
		bit.update(item, 1)
	return result

def discrete_by_permutation(seq1, seq2):
	(seq1, seq2) = (reversed(seq1), tuple(seq2))
	d_stack = defaultdict(lambda : [])
	for (index, item) in enumerate(seq2):
		d_stack[item].append(index)
	return list(reversed([d_stack[item].pop() for item in seq1]))

def bubble_step(s1, s2):
	return sum(inversion(discrete_by_permutation(s1, s2)))

def main():
	(_, s) = (itg(), inp())
	return bubble_step(s, s[::-1])
(sys.stdin, sys.stdout) = (IOWrapper(sys.stdin), IOWrapper(sys.stdout))
print(main())


count = 0

def merge_count(arr):
	if len(arr) == 1:
		return arr
	global count
	mid = len(arr) // 2
	l = merge_count(arr[:mid])
	r = merge_count(arr[mid:])
	new_arr = []
	(lp, rp) = (0, 0)
	while lp < len(l) and rp < len(r):
		if l[lp] <= r[rp]:
			new_arr.append(l[lp])
			lp += 1
		else:
			count += len(l) - lp
			new_arr.append(r[rp])
			rp += 1
	while lp < len(l):
		new_arr.append(l[lp])
		lp += 1
	while rp < len(r):
		new_arr.append(r[rp])
		rp += 1
	return new_arr

def solve(n, s):
	arr = [0 for _ in s]
	for chi in range(26):
		indexes = []
		ch = chr(ord('a') + chi)
		for i in range(n):
			if s[i] == ch:
				indexes.append(i)
		m = len(indexes)
		for i in range(m):
			(x, y) = (indexes[i], n - 1 - indexes[m - 1 - i])
			arr[x] = y
	global count
	count = 0
	merge_count(arr)
	return count
print(solve(int(input()), input()))


from bisect import bisect_left as bl
from bisect import bisect_right as br
from heapq import heappush, heappop, heapify
import math
from collections import *
from functools import reduce, cmp_to_key
import sys
input = sys.stdin.readline
from itertools import accumulate, permutations
from functools import lru_cache
M = mod = 998244353

def factors(n):
	return sorted(set(reduce(list.__add__, ([i, n // i] for i in range(1, int(n ** 0.5) + 1) if n % i == 0))))

def inv_mod(n):
	return pow(n, mod - 2, mod)

def li():
	return [int(i) for i in input().rstrip('\n').split()]

def st():
	return input().rstrip('\n')

def val():
	return int(input().rstrip('\n'))

def li2():
	return [i for i in input().rstrip('\n')]

def li3():
	return [int(i) for i in input().rstrip('\n')]

class Node:

	def __init__(self, s, e):
		self.start = s
		self.end = e
		self.val = 0
		self.left = None
		self.right = None

def build(nums, l, r):
	if l == r:
		temp = Node(l, l)
		temp.val = nums[l]
	else:
		mid = l + r >> 1
		temp = Node(l, r)
		temp.left = build(nums, l, mid)
		temp.right = build(nums, mid + 1, r)
		temp.val = temp.left.val + temp.right.val
	return temp

def update(root, start, value):
	if root.start == start == root.end:
		root.val += value
	elif root.start <= start and root.end >= start:
		update(root.left, start, value)
		update(root.right, start, value)
		root.val = root.left.val + root.right.val

def query(root, start, end):
	if root.start >= start and root.end <= end:
		return root.val
	elif root.start > end or root.end < start:
		return 0
	else:
		temp1 = query(root.left, start, end)
		temp2 = query(root.right, start, end)
		return temp1 + temp2
n = val()
s = st()
index = defaultdict(deque)
for i in range(n):
	index[s[i]].append(i)
s1 = s[::-1]
N = 2 * 10 ** 5 + 10
root = build([0] * N, 0, N - 1)
ans = 0
pointer = 0
myset = set()
for i in range(n):
	ind1 = index[s1[i]].popleft()
	if ind1 == pointer:
		myset.add(pointer)
		while pointer in myset:
			pointer += 1
	else:
		myset.add(ind1)
		ans += ind1 - pointer
		ans -= query(root, pointer, ind1)
	update(root, ind1, 1)
print(ans)


from collections import defaultdict
import sys
input = sys.stdin.readline

def getsum(BITTree, i):
	i = i + 1
	s = 0
	while i > 0:
		s += BITTree[i]
		i -= i & -i
	return s

def updatebit(BITTree, n, i, v):
	i = i + 1
	while i <= n:
		BITTree[i] += v
		i += i & -i
n = int(input())
l = [i for i in input() if i != '\n']
rev = l[::-1]
dicta = defaultdict(list)
for i in range(n - 1, -1, -1):
	dicta[l[i]].append(i)
for i in range(n):
	top = dicta[rev[i]].pop()
	l[top] = i
bit = [0] * (n + 2)
inv = 0
for k in reversed(l):
	updatebit(bit, n + 1, k, 1)
	inv += getsum(bit, k - 1)
print(inv)


import sys
import random
import math
import copy
from heapq import heappush, heappop, heapify
from functools import cmp_to_key
from bisect import bisect_left, bisect_right
from collections import defaultdict, deque, Counter
input = sys.stdin.readline
getS = lambda : input().strip()
getN = lambda : int(input())
getList = lambda : list(map(int, input().split()))
getZList = lambda : [int(x) - 1 for x in input().split()]
INF = float('inf')
MOD = 10 ** 9 + 7
divide = lambda x: pow(x, MOD - 2, MOD)
q = [deque() for i in range(26)]
passed = [0] * 26
import sys
input = sys.stdin.readline
sys.setrecursionlimit(10000)
from collections import deque, Counter, defaultdict

def getN():
	return int(input())

def getList():
	return list(map(int, input().split()))
import math
MOD = 10 ** 9 + 7
INF = 10 ** 20

class Segtree_op:

	def __init__(self, n):
		self.size = 1
		while n >= 1:
			self.size = self.size << 1
			n = n // 2
		self.arr = [self.unit() for i in range(self.size * 2)]

	def op(self, lch, rch):
		return lch + rch

	def unit(self):
		return 0

	def update(self, k, val):
		k += self.size - 1
		self.arr[k] = val
		while k:
			k = (k - 1) // 2
			self.arr[k] = self.op(self.arr[k * 2 + 1], self.arr[k * 2 + 2])

	def query(self, l, r):
		L = l + self.size
		R = r + self.size
		s = self.unit()
		while L < R:
			if R & 1:
				R -= 1
				s = self.op(s, self.arr[R - 1])
			if L & 1:
				s = self.op(s, self.arr[L - 1])
				L += 1
			L >>= 1
			R >>= 1
		return s

	def show(self):
		idx = 1
		while idx <= self.size:
			print(self.arr[idx - 1:idx * 2 - 1])
			idx *= 2

def dapp(c, n):
	q[ord(c) - ord('a')].append(n)
	return

def dpopl(c):
	return q[ord(c) - ord('a')].popleft()

def getpassed(c):
	return passed[ord(c) - ord('a')]

def setpassed(c, v):
	passed[ord(c) - ord('a')] += v
	return

def solve():
	n = getN()
	q = [deque() for i in range(26)]
	s = getS()
	for (i, c) in enumerate(s):
		dapp(c, i)
	imost = Segtree_op(n + 1)
	ans = 0
	for (i, c) in enumerate(reversed(s)):
		target = dpopl(c)
		oikoshi = imost.query(0, target + 1)
		ans += target + oikoshi - i
		imost.update(0, imost.query(0, 1) + 1)
		imost.update(target + 1, imost.query(target + 1, target + 2) - 1)
	print(ans)

def main():
	n = getN()
	for _ in range(n):
		solve()
	return
solve()


import sys
input = sys.stdin.readline
(inp, ip) = (lambda : int(input()), lambda : [int(w) for w in input().split()])

def update(i, val):
	i += 1
	while i <= n:
		BIT[i] += val
		i += i & -i

def getsum(i):
	sm = 0
	i += 1
	while i:
		sm += BIT[i]
		i -= i & -i
	return sm
n = inp()
s = input().strip()
if s == s[::-1]:
	print(0)
	exit()
dt = [[] for i in range(26)]
for i in range(n - 1, -1, -1):
	dt[ord(s[i]) - 97].append(i)
BIT = [0] * (n + 1)
ans = 0
for i in range(n):
	ind = dt[ord(s[n - i - 1]) - 97].pop(-1)
	put = getsum(ind)
	ans += ind - put
	update(ind, 1)
print(ans)


import sys
__lines = list(sys.stdin.readlines())
__cur_line = 0

def input():
	global __lines, __cur_line
	ans = __lines[__cur_line]
	__cur_line += 1
	return ans

class SegmentTree:

	def __init__(self, n):
		self.size = 1
		while self.size < n:
			self.size *= 2
		self.vals = [0] * (2 * self.size)

	def set(self, i, v):
		return self._set(i, v, 0, 0, self.size)

	def _set(self, i, v, x, lx, rx):
		if rx - lx == 1:
			self.vals[x] = v
		else:
			m = (lx + rx) // 2
			if i < m:
				self._set(i, v, x * 2 + 1, lx, m)
			else:
				self._set(i, v, x * 2 + 2, m, rx)
			self.vals[x] = self.vals[2 * x + 1] + self.vals[2 * x + 2]

	def range(self, l, r):
		return self._range(l, r, 0, 0, self.size)

	def _range(self, l, r, x, lx, rx):
		if r <= lx or rx <= l:
			return 0
		if l <= lx and rx <= r:
			return self.vals[x]
		m = (lx + rx) // 2
		s = 0
		if l < m:
			s += self._range(l, r, x * 2 + 1, lx, m)
		if m < r:
			s += self._range(l, r, x * 2 + 2, m, rx)
		return s
n = int(input())
s = input().strip()
poss = [[] for _ in range(26)]
for (i, c) in enumerate(s):
	poss[ord(c) - ord('a')].append(i)
target_pos = [0] * n
for l in poss:
	l2 = [n - 1 - i for i in l][::-1]
	for (x1, x2) in zip(l, l2):
		target_pos[x1] = x2
total = 0
st = SegmentTree(n)
for pos in target_pos:
	total += st.range(pos + 1, n)
	st.set(pos, 1)
print(total)


n = int(input())
A = input()
flippedA = A[::-1]
revs = [i + 1 for i in range(len(A))]
freqs = dict()
for i in range(len(flippedA)):
	if flippedA[i] not in freqs:
		freqs[flippedA[i]] = [i + 1]
	else:
		freqs[flippedA[i]].append(i + 1)
origs = []
ptr = [0 for i in range(26)]
for i in range(len(A)):
	origs.append(freqs[A[i]][ptr[ord(A[i]) - ord('a')]])
	ptr[ord(A[i]) - ord('a')] += 1

def inversions(A):
	ans = 0
	for i in range(len(A)):
		for j in range(i + 1, len(A)):
			if A[i] > A[j]:
				ans += 1
	return ans
fenw = [0 for i in range(n + 5)]

def update(idx, val):
	while idx <= n + 1:
		fenw[idx] += val
		idx += idx & -idx

def query(idx):
	ans = 0
	while idx > 0:
		ans += fenw[idx]
		idx -= idx & -idx
	return ans

def solve(l, r):
	return query(r) - query(l - 1)

def inversions(A):
	ans = 0
	for i in range(n):
		ans += solve(A[i] + 1, n)
		update(A[i], 1)
	return ans
print(inversions(origs))


import sys
from collections import deque
input = sys.stdin.buffer.readline
n = int(input())
a = list(input())
a = a[:n]

def segfunc(x, y):
	return x + y

def init(init_val):
	for i in range(n):
		seg[i + num - 1] = init_val[i]
	for i in range(num - 2, -1, -1):
		seg[i] = segfunc(seg[2 * i + 1], seg[2 * i + 2])

def update(k, x):
	k += num - 1
	seg[k] = x
	while k:
		k = (k - 1) // 2
		seg[k] = segfunc(seg[k * 2 + 1], seg[k * 2 + 2])

def query(p, q):
	if q <= p:
		return ide_ele
	p += num - 1
	q += num - 2
	res = ide_ele
	while q - p > 1:
		if p & 1 == 0:
			res = segfunc(res, seg[p])
		if q & 1 == 1:
			res = segfunc(res, seg[q])
			q -= 1
		p = p // 2
		q = (q - 1) // 2
	if p == q:
		res = segfunc(res, seg[p])
	else:
		res = segfunc(segfunc(res, seg[p]), seg[q])
	return res
ide_ele = 0
num = 2 ** (n - 1).bit_length()
seg = [ide_ele] * 2 * num
for i in range(n):
	a[i] -= 97
p = [deque([]) for i in range(26)]
for i in range(n):
	p[a[i]].append(i)
a = a[::-1]
res = 0
for i in range(n):
	v = p[a[i]].popleft()
	plus = query(v, n)
	res += v + plus - i
	update(v, 1)
print(res)


from math import log2

class Sparse:

	def __init__(self, a, func=min):
		self.a = a
		self.n = len(a)
		self.k = int(log2(self.n)) + 1
		self.func = func
		self.lookup = [[0] * self.k for _ in range(self.n)]
		self.process()

	def process(self):
		for i in range(self.n):
			self.lookup[i][0] = self.a[i]
		j = 1
		while 1 << j <= self.n:
			i = 0
			while i + (1 << j) - 1 < self.n:
				self.lookup[i][j] = self.func(self.lookup[i][j - 1], self.lookup[i + (1 << j - 1)][j - 1])
				i += 1
			j += 1

	def query(self, alpha, omega):
		x = int(log2(omega - alpha + 1))
		return self.func(self.lookup[alpha][x], self.lookup[omega - (1 << x) + 1][x])
from math import inf, log2

class SegmentTree:

	def __init__(self, array, func=max):
		self.n = len(array)
		self.size = 2 ** (int(log2(self.n - 1)) + 1) if self.n != 1 else 1
		self.func = func
		self.default = 0 if self.func != min else inf
		self.data = [self.default] * (2 * self.size)
		self.process(array)

	def process(self, array):
		self.data[self.size:self.size + self.n] = array
		for i in range(self.size - 1, -1, -1):
			self.data[i] = self.func(self.data[2 * i], self.data[2 * i + 1])

	def query(self, alpha, omega):
		if alpha == omega:
			return self.data[alpha + self.size]
		res = self.default
		alpha += self.size
		omega += self.size + 1
		while alpha < omega:
			if alpha & 1:
				res = self.func(res, self.data[alpha])
				alpha += 1
			if omega & 1:
				omega -= 1
				res = self.func(res, self.data[omega])
			alpha >>= 1
			omega >>= 1
		return res

	def update(self, index, value):
		index += self.size
		self.data[index] = value
		index >>= 1
		while index:
			self.data[index] = self.func(self.data[2 * index], self.data[2 * index + 1])
			index >>= 1
import os
import sys
from io import BytesIO, IOBase
BUFSIZE = 8192

class FastIO(IOBase):
	newlines = 0

	def __init__(self, file):
		self._fd = file.fileno()
		self.buffer = BytesIO()
		self.writable = 'x' in file.mode or 'r' not in file.mode
		self.write = self.buffer.write if self.writable else None

	def read(self):
		while True:
			b = os.read(self._fd, max(os.fstat(self._fd).st_size, BUFSIZE))
			if not b:
				break
			ptr = self.buffer.tell()
			(self.buffer.seek(0, 2), self.buffer.write(b), self.buffer.seek(ptr))
		self.newlines = 0
		return self.buffer.read()

	def readline(self):
		while self.newlines == 0:
			b = os.read(self._fd, max(os.fstat(self._fd).st_size, BUFSIZE))
			self.newlines = b.count(b'\n') + (not b)
			ptr = self.buffer.tell()
			(self.buffer.seek(0, 2), self.buffer.write(b), self.buffer.seek(ptr))
		self.newlines -= 1
		return self.buffer.readline()

	def flush(self):
		if self.writable:
			os.write(self._fd, self.buffer.getvalue())
			(self.buffer.truncate(0), self.buffer.seek(0))

class IOWrapper(IOBase):

	def __init__(self, file):
		self.buffer = FastIO(file)
		self.flush = self.buffer.flush
		self.writable = self.buffer.writable
		self.write = lambda s: self.buffer.write(s.encode('ascii'))
		self.read = lambda : self.buffer.read().decode('ascii')
		self.readline = lambda : self.buffer.readline().decode('ascii')
(sys.stdin, sys.stdout) = (IOWrapper(sys.stdin), IOWrapper(sys.stdout))
input = lambda : sys.stdin.readline().rstrip('\r\n')
from math import gcd, ceil

def prod(a, mod=10 ** 9 + 7):
	ans = 1
	for each in a:
		ans = ans * each % mod
	return ans

def lcm(a, b):
	return a * b // gcd(a, b)

def binary(x, length=16):
	y = bin(x)[2:]
	return y if len(y) >= length else '0' * (length - len(y)) + y
from collections import deque
for _ in range(int(input()) if not True else 1):
	n = int(input())
	s = input()
	ind = [deque() for i in range(26)]
	for i in range(n):
		ind[ord(s[i]) - 97].append(i)
	a = []
	for i in range(n - 1, -1, -1):
		a += [ind[ord(s[i]) - 97].popleft()]
	ans = 0
	st = SegmentTree([0] * 200300, func=lambda a, b: a + b)
	for i in range(n):
		val = a[i] + st.query(a[i], 200200)
		st.update(a[i], 1)
		ans += val - i
	print(ans)


import os
import sys
from io import BytesIO, IOBase

def main():
	n = int(input())
	s = input()
	pos = [[] for _ in range(26)]
	order = [-1] * n
	for (i, c) in enumerate(s):
		pos[ord(c) - 97].append(i)
	for (i, c) in enumerate(s):
		order[i] = pos[ord(c) - 97].pop()
	bit = [0] * n
	ans = 0
	for o in order:
		x = o + 1
		while x:
			ans += bit[x - 1]
			x &= x - 1
		x = o
		while x < n:
			bit[x] += 1
			x |= x + 1
	print(ans)
BUFSIZE = 8192

class FastIO(IOBase):
	newlines = 0

	def __init__(self, file):
		self._fd = file.fileno()
		self.buffer = BytesIO()
		self.writable = 'x' in file.mode or 'r' not in file.mode
		self.write = self.buffer.write if self.writable else None

	def read(self):
		while True:
			b = os.read(self._fd, max(os.fstat(self._fd).st_size, BUFSIZE))
			if not b:
				break
			ptr = self.buffer.tell()
			(self.buffer.seek(0, 2), self.buffer.write(b), self.buffer.seek(ptr))
		self.newlines = 0
		return self.buffer.read()

	def readline(self):
		while self.newlines == 0:
			b = os.read(self._fd, max(os.fstat(self._fd).st_size, BUFSIZE))
			self.newlines = b.count(b'\n') + (not b)
			ptr = self.buffer.tell()
			(self.buffer.seek(0, 2), self.buffer.write(b), self.buffer.seek(ptr))
		self.newlines -= 1
		return self.buffer.readline()

	def flush(self):
		if self.writable:
			os.write(self._fd, self.buffer.getvalue())
			(self.buffer.truncate(0), self.buffer.seek(0))

class IOWrapper(IOBase):

	def __init__(self, file):
		self.buffer = FastIO(file)
		self.flush = self.buffer.flush
		self.writable = self.buffer.writable
		self.write = lambda s: self.buffer.write(s.encode('ascii'))
		self.read = lambda : self.buffer.read().decode('ascii')
		self.readline = lambda : self.buffer.readline().decode('ascii')
(sys.stdin, sys.stdout) = (IOWrapper(sys.stdin), IOWrapper(sys.stdout))

def input():
	return sys.stdin.readline().rstrip('\r\n')

def getint():
	return int(input())

def getints():
	return list(map(int, input().split()))

def getint1():
	return list(map(lambda x: int(x) - 1, input().split()))
main()


class SortedList:

	def __init__(self, iterable=[], _load=200):
		values = sorted(iterable)
		self._len = _len = len(values)
		self._load = _load
		self._lists = _lists = [values[i:i + _load] for i in range(0, _len, _load)]
		self._list_lens = [len(_list) for _list in _lists]
		self._mins = [_list[0] for _list in _lists]
		self._fen_tree = []
		self._rebuild = True

	def _fen_build(self):
		self._fen_tree[:] = self._list_lens
		_fen_tree = self._fen_tree
		for i in range(len(_fen_tree)):
			if i | i + 1 < len(_fen_tree):
				_fen_tree[i | i + 1] += _fen_tree[i]
		self._rebuild = False

	def _fen_update(self, index, value):
		if not self._rebuild:
			_fen_tree = self._fen_tree
			while index < len(_fen_tree):
				_fen_tree[index] += value
				index |= index + 1

	def _fen_query(self, end):
		if self._rebuild:
			self._fen_build()
		_fen_tree = self._fen_tree
		x = 0
		while end:
			x += _fen_tree[end - 1]
			end &= end - 1
		return x

	def _fen_findkth(self, k):
		_list_lens = self._list_lens
		if k < _list_lens[0]:
			return (0, k)
		if k >= self._len - _list_lens[-1]:
			return (len(_list_lens) - 1, k + _list_lens[-1] - self._len)
		if self._rebuild:
			self._fen_build()
		_fen_tree = self._fen_tree
		idx = -1
		for d in reversed(range(len(_fen_tree).bit_length())):
			right_idx = idx + (1 << d)
			if right_idx < len(_fen_tree) and k >= _fen_tree[right_idx]:
				idx = right_idx
				k -= _fen_tree[idx]
		return (idx + 1, k)

	def _delete(self, pos, idx):
		_lists = self._lists
		_mins = self._mins
		_list_lens = self._list_lens
		self._len -= 1
		self._fen_update(pos, -1)
		del _lists[pos][idx]
		_list_lens[pos] -= 1
		if _list_lens[pos]:
			_mins[pos] = _lists[pos][0]
		else:
			del _lists[pos]
			del _list_lens[pos]
			del _mins[pos]
			self._rebuild = True

	def _loc_left(self, value):
		if not self._len:
			return (0, 0)
		_lists = self._lists
		_mins = self._mins
		(lo, pos) = (-1, len(_lists) - 1)
		while lo + 1 < pos:
			mi = lo + pos >> 1
			if value <= _mins[mi]:
				pos = mi
			else:
				lo = mi
		if pos and value <= _lists[pos - 1][-1]:
			pos -= 1
		_list = _lists[pos]
		(lo, idx) = (-1, len(_list))
		while lo + 1 < idx:
			mi = lo + idx >> 1
			if value <= _list[mi]:
				idx = mi
			else:
				lo = mi
		return (pos, idx)

	def _loc_right(self, value):
		if not self._len:
			return (0, 0)
		_lists = self._lists
		_mins = self._mins
		(pos, hi) = (0, len(_lists))
		while pos + 1 < hi:
			mi = pos + hi >> 1
			if value < _mins[mi]:
				hi = mi
			else:
				pos = mi
		_list = _lists[pos]
		(lo, idx) = (-1, len(_list))
		while lo + 1 < idx:
			mi = lo + idx >> 1
			if value < _list[mi]:
				idx = mi
			else:
				lo = mi
		return (pos, idx)

	def add(self, value):
		_load = self._load
		_lists = self._lists
		_mins = self._mins
		_list_lens = self._list_lens
		self._len += 1
		if _lists:
			(pos, idx) = self._loc_right(value)
			self._fen_update(pos, 1)
			_list = _lists[pos]
			_list.insert(idx, value)
			_list_lens[pos] += 1
			_mins[pos] = _list[0]
			if _load + _load < len(_list):
				_lists.insert(pos + 1, _list[_load:])
				_list_lens.insert(pos + 1, len(_list) - _load)
				_mins.insert(pos + 1, _list[_load])
				_list_lens[pos] = _load
				del _list[_load:]
				self._rebuild = True
		else:
			_lists.append([value])
			_mins.append(value)
			_list_lens.append(1)
			self._rebuild = True

	def discard(self, value):
		_lists = self._lists
		if _lists:
			(pos, idx) = self._loc_right(value)
			if idx and _lists[pos][idx - 1] == value:
				self._delete(pos, idx - 1)

	def remove(self, value):
		_len = self._len
		self.discard(value)
		if _len == self._len:
			raise ValueError('{0!r} not in list'.format(value))

	def pop(self, index=-1):
		(pos, idx) = self._fen_findkth(self._len + index if index < 0 else index)
		value = self._lists[pos][idx]
		self._delete(pos, idx)
		return value

	def bisect_left(self, value):
		(pos, idx) = self._loc_left(value)
		return self._fen_query(pos) + idx

	def bisect_right(self, value):
		(pos, idx) = self._loc_right(value)
		return self._fen_query(pos) + idx

	def count(self, value):
		return self.bisect_right(value) - self.bisect_left(value)

	def __len__(self):
		return self._len

	def __getitem__(self, index):
		(pos, idx) = self._fen_findkth(self._len + index if index < 0 else index)
		return self._lists[pos][idx]

	def __delitem__(self, index):
		(pos, idx) = self._fen_findkth(self._len + index if index < 0 else index)
		self._delete(pos, idx)

	def __contains__(self, value):
		_lists = self._lists
		if _lists:
			(pos, idx) = self._loc_left(value)
			return idx < len(_lists[pos]) and _lists[pos][idx] == value
		return False

	def __iter__(self):
		return (value for _list in self._lists for value in _list)

	def __reversed__(self):
		return (value for _list in reversed(self._lists) for value in reversed(_list))

	def __repr__(self):
		return 'SortedList({0})'.format(list(self))

class OrderedList(SortedList):

	def __init__(self, arg):
		super().__init__(arg)

	def rangeCountByValue(self, leftVal, rightVal):
		leftCummulative = self.bisect_left(leftVal)
		rightCummulative = self.bisect_left(rightVal + 1)
		return rightCummulative - leftCummulative
from collections import defaultdict

def main():
	n = int(input())
	s = input()
	indexes = defaultdict(lambda : [])
	for i in range(n - 1, -1, -1):
		indexes[s[i]].append(i)
	ol = SortedList(list(range(n)))
	rev = s[::-1]
	ans = 0
	for c in rev:
		i = indexes[c].pop()
		ans += ol.bisect_left(i)
		ol.remove(i)
	print(ans)
	return
import sys
input = lambda : sys.stdin.readline().rstrip('\r\n')

def oneLineArrayPrint(arr):
	print(' '.join([str(x) for x in arr]))

def multiLineArrayPrint(arr):
	print('\n'.join([str(x) for x in arr]))

def multiLineArrayOfArraysPrint(arr):
	print('\n'.join([' '.join([str(x) for x in y]) for y in arr]))

def readIntArr():
	return [int(x) for x in input().split()]

def makeArr(defaultValFactory, dimensionArr):
	dv = defaultValFactory
	da = dimensionArr
	if len(da) == 1:
		return [dv() for _ in range(da[0])]
	else:
		return [makeArr(dv, da[1:]) for _ in range(da[0])]

def queryInteractive(i, j):
	print('? {} {}'.format(i, j))
	sys.stdout.flush()
	return int(input())

def answerInteractive(ans):
	print('! {}'.format(' '.join([str(x) for x in ans])))
	sys.stdout.flush()
inf = float('inf')
MOD = 10 ** 9 + 7
for _abc in range(1):
	main()


n = int(input())
s = input()
s1 = s[-1::-1]
d = [[] for _ in range(26)]
for i in range(n):
	d[ord(s1[i]) - 97].append(i)
dp = []
mp = [0] * 26
for i in range(n):
	tp = ord(s[i]) - 97
	dp.append(d[tp][mp[tp]])
	mp[tp] += 1
LEN = n + 1
BIT = [0] * (LEN + 1)

def update(v, w):
	while v <= LEN:
		BIT[v] += w
		v += v & -v

def getvalue(v):
	ANS = 0
	while v != 0:
		ANS += BIT[v]
		v -= v & -v
	return ANS
ans = 0
for i in range(n - 1, -1, -1):
	ans += getvalue(dp[i] + 1)
	update(dp[i] + 1, 1)
print(ans)


import math, sys, os
from collections import defaultdict, deque, OrderedDict, Counter
import bisect as bi
from io import BytesIO, IOBase
mod = 10 ** 9 + 7
BUFSIZE = 8192

class FastIO(IOBase):
	newlines = 0

	def __init__(self, file):
		self._fd = file.fileno()
		self.buffer = BytesIO()
		self.writable = 'x' in file.mode or 'r' not in file.mode
		self.write = self.buffer.write if self.writable else None

	def read(self):
		while True:
			b = os.read(self._fd, max(os.fstat(self._fd).st_size, BUFSIZE))
			if not b:
				break
			ptr = self.buffer.tell()
			(self.buffer.seek(0, 2), self.buffer.write(b), self.buffer.seek(ptr))
		self.newlines = 0
		return self.buffer.read()

	def readline(self):
		while self.newlines == 0:
			b = os.read(self._fd, max(os.fstat(self._fd).st_size, BUFSIZE))
			self.newlines = b.count(b'\n') + (not b)
			ptr = self.buffer.tell()
			(self.buffer.seek(0, 2), self.buffer.write(b), self.buffer.seek(ptr))
		self.newlines -= 1
		return self.buffer.readline()

	def flush(self):
		if self.writable:
			os.write(self._fd, self.buffer.getvalue())
			(self.buffer.truncate(0), self.buffer.seek(0))

class IOWrapper(IOBase):

	def __init__(self, file):
		self.buffer = FastIO(file)
		self.flush = self.buffer.flush
		self.writable = self.buffer.writable
		self.write = lambda s: self.buffer.write(s.encode('ascii'))
		self.read = lambda : self.buffer.read().decode('ascii')
		self.readline = lambda : self.buffer.readline().decode('ascii')
(sys.stdin, sys.stdout) = (IOWrapper(sys.stdin), IOWrapper(sys.stdout))
input = lambda : sys.stdin.readline().rstrip('\r\n')

def minp():
	return map(int, sys.stdin.readline().rstrip().split())

def linp():
	return list(map(int, sys.stdin.readline().rstrip().split()))

def inp():
	return int(input())

def print_list(l):
	print(' '.join(map(str, l)))

def BinarySearch(a, x):
	i = bi.bisect_left(a, x)
	if i != len(a) and a[i] == x:
		return i
	else:
		return -1

def gcd(a, b):
	return math.gcd(a, b)

def is_prime(n):
	if n < 5 or n & 1 == 0 or n % 3 == 0:
		return 2 <= n <= 3
	s = (n - 1 & 1 - n).bit_length() - 1
	d = n >> s
	for a in [2, 325, 9375, 28178, 450775, 9780504, 1795265022]:
		p = pow(a, d, n)
		if p == 1 or p == n - 1 or a % n == 0:
			continue
		for _ in range(s):
			p = p * p % n
			if p == n - 1:
				break
		else:
			return False
	return True

def mulinverse(a):
	return pow(a, mod - 2, mod)
from collections import defaultdict as dc

def reversePairs(nums):
	if not nums:
		return 0
	res = 0

	def merge(a, b):
		nonlocal res
		temp = []
		(i, j) = (0, 0)
		m = len(a)
		n = len(b)
		while i < m and j < n:
			if a[i] <= b[j]:
				temp.append(a[i])
				i += 1
			else:
				temp.append(b[j])
				j += 1
				res += m - i
		if i < m:
			temp += a[i:]
		else:
			temp += b[j:]
		return temp

	def mergesort(L):
		length = len(L)
		if length == 1:
			return L
		k = length >> 1
		a = mergesort(L[:k])
		b = mergesort(L[k:])
		return merge(a, b)
	mergesort(nums)
	return res
n = inp()
s = input()
t = s[::-1]
res = 0
flag = [0] * n
dic = dc(int)
for i in range(n):
	c = t[i]
	key = s.find(c, dic[c])
	dic[c] = key + 1
	flag[key] = i
print(reversePairs(flag))


import sys
import math
from collections import defaultdict, Counter, deque
import os
import sys
from io import BytesIO, IOBase
BUFSIZE = 8192

class FastIO(IOBase):
	newlines = 0

	def __init__(self, file):
		self._fd = file.fileno()
		self.buffer = BytesIO()
		self.writable = 'x' in file.mode or 'r' not in file.mode
		self.write = self.buffer.write if self.writable else None

	def read(self):
		while True:
			b = os.read(self._fd, max(os.fstat(self._fd).st_size, BUFSIZE))
			if not b:
				break
			ptr = self.buffer.tell()
			(self.buffer.seek(0, 2), self.buffer.write(b), self.buffer.seek(ptr))
		self.newlines = 0
		return self.buffer.read()

	def readline(self):
		while self.newlines == 0:
			b = os.read(self._fd, max(os.fstat(self._fd).st_size, BUFSIZE))
			self.newlines = b.count(b'\n') + (not b)
			ptr = self.buffer.tell()
			(self.buffer.seek(0, 2), self.buffer.write(b), self.buffer.seek(ptr))
		self.newlines -= 1
		return self.buffer.readline()

	def flush(self):
		if self.writable:
			os.write(self._fd, self.buffer.getvalue())
			(self.buffer.truncate(0), self.buffer.seek(0))

class IOWrapper(IOBase):

	def __init__(self, file):
		self.buffer = FastIO(file)
		self.flush = self.buffer.flush
		self.writable = self.buffer.writable
		self.write = lambda s: self.buffer.write(s.encode('ascii'))
		self.read = lambda : self.buffer.read().decode('ascii')
		self.readline = lambda : self.buffer.readline().decode('ascii')
(sys.stdin, sys.stdout) = (IOWrapper(sys.stdin), IOWrapper(sys.stdout))
input = lambda : sys.stdin.readline().rstrip('\r\n')

def getsum(BIT, i):
	s = 0
	i += 1
	while i > 0:
		s += BIT[i]
		i -= i & -i
	return s

def updatebit(BIT, n, i, v):
	i += 1
	while i <= n:
		BIT[i] += v
		i += i & -i
n = int(input())
s = input()
d = defaultdict(deque)
for j in range(n):
	d[s[j]].append(j)
l = []
ans = 0
BIT = [0] * (n + 1)
for j in range(n - 1):
	p = d[s[-(j + 1)]].popleft()
	c = getsum(BIT, p)
	ans += p + c - j
	updatebit(BIT, n, 0, 1)
	updatebit(BIT, n, p, -1)
print(ans)


import os, sys
from io import BytesIO, IOBase
from math import log2, ceil, sqrt, gcd
from _collections import deque
import heapq as hp
from bisect import bisect_left, bisect_right
from math import cos, sin
BUFSIZE = 8192

class FastIO(IOBase):
	newlines = 0

	def __init__(self, file):
		self._fd = file.fileno()
		self.buffer = BytesIO()
		self.writable = 'x' in file.mode or 'r' not in file.mode
		self.write = self.buffer.write if self.writable else None

	def read(self):
		while True:
			b = os.read(self._fd, max(os.fstat(self._fd).st_size, BUFSIZE))
			if not b:
				break
			ptr = self.buffer.tell()
			(self.buffer.seek(0, 2), self.buffer.write(b), self.buffer.seek(ptr))
		self.newlines = 0
		return self.buffer.read()

	def readline(self):
		while self.newlines == 0:
			b = os.read(self._fd, max(os.fstat(self._fd).st_size, BUFSIZE))
			self.newlines = b.count(b'\n') + (not b)
			ptr = self.buffer.tell()
			(self.buffer.seek(0, 2), self.buffer.write(b), self.buffer.seek(ptr))
		self.newlines -= 1
		return self.buffer.readline()

	def flush(self):
		if self.writable:
			os.write(self._fd, self.buffer.getvalue())
			(self.buffer.truncate(0), self.buffer.seek(0))

class IOWrapper(IOBase):

	def __init__(self, file):
		self.buffer = FastIO(file)
		self.flush = self.buffer.flush
		self.writable = self.buffer.writable
		self.write = lambda s: self.buffer.write(s.encode('ascii'))
		self.read = lambda : self.buffer.read().decode('ascii')
		self.readline = lambda : self.buffer.readline().decode('ascii')
(sys.stdin, sys.stdout) = (IOWrapper(sys.stdin), IOWrapper(sys.stdout))
input = lambda : sys.stdin.readline().rstrip('\r\n')
mod = 10 ** 9 + 7

def update(i, vl):
	i += n
	tree[i] += vl
	while i:
		tree[i >> 1] = tree[i] + tree[i ^ 1]
		i >>= 1

def query(l, r):
	l += n
	r += n
	ans = 0
	while l < r:
		if l & 1:
			ans += tree[l]
			l += 1
		if r & 1:
			r -= 1
			ans += tree[r]
		l >>= 1
		r >>= 1
	return ans
n = int(input())
tree = [0] * (2 * n)
a = [i for i in input()]
d = dict()
for (i, v) in enumerate(a):
	d[v] = d.get(v, [])
	d[v].append(i)
for i in d:
	d[i].sort(reverse=True)
ans = 0
for (i, v) in enumerate(reversed(a)):
	t = d[v].pop()
	ct = query(0, t + 1)
	ans += abs(i - t - ct)
	update(0, 1)
	update(t, -1)
print(ans)


from collections import deque
import bisect

def invNumCount(A):
	N = len(A)
	res = 0
	BIT = [0] * (N + 1)

	def BIT_query(idx):
		res_sum = 0
		while idx > 0:
			res_sum += BIT[idx]
			idx -= idx & -idx
		return res_sum

	def BIT_update(idx, x):
		while idx <= N:
			BIT[idx] += x
			idx += idx & -idx
		return
	B = sorted(A)
	for (i, e) in enumerate(A):
		A[i] = bisect.bisect_left(B, e)
	for (i, e) in enumerate(A):
		res += i - BIT_query(e + 1)
		BIT_update(e + 1, 1)
	return res
n = int(input())
s = list(input())
dic = {}
for i in range(n):
	if s[i] in dic:
		dic[s[i]].append(i)
	else:
		dic[s[i]] = deque([i])
reverse = [s[n - i - 1] for i in range(n)]
res = []
for i in range(n):
	res.append(dic[reverse[i]].popleft())
ans = invNumCount(res)
print(ans)


n = int(input())
s = input()
SZ = 30
lim = n + 233
g = [[] for i in range(SZ)]
a = [0] * SZ
for i in range(n):
	cur = ord(s[i]) - 97
	g[cur].append(i)
bit = [0] * (lim + 1)

def lowbit(x):
	return x & -x

def add(pos, val):
	while pos <= lim:
		bit[pos] += val
		pos += lowbit(pos)

def query(pos):
	res = 0
	while pos:
		res += bit[pos]
		pos -= lowbit(pos)
	return res
ans = 0
for i in range(n - 1, -1, -1):
	cur = ord(s[i]) - 97
	val = g[cur][a[cur]]
	ans += val - query(val + 1)
	a[cur] += 1
	add(val + 1, 1)
print(ans)


import sys
input = sys.stdin.readline

class Bit:

	def __init__(self, n):
		self.size = n
		self.tree = [0] * (n + 1)

	def sum(self, i):
		s = 0
		while i > 0:
			s += self.tree[i]
			i -= i & -i
		return s

	def add(self, i, x):
		while i <= self.size:
			self.tree[i] += x
			i += i & -i
n = int(input())
s = list(input().rstrip())
rev_s = s[::-1]
p = [0] * n
cnt = [0] * 26
pos = [[] for i in range(26)]
for i in range(n):
	pos[ord(s[i]) - ord('a')].append(i)
for i in range(n):
	x = ord(rev_s[i]) - ord('a')
	cur = pos[x][cnt[x]]
	p[i] = cur
	cnt[x] += 1
for i in range(n):
	p[i] += 1
bit = Bit(n)
ans = 0
for (i, x) in enumerate(p):
	bit.add(x, 1)
	ans += i + 1 - bit.sum(x)
print(ans)


import collections

class RangeAddList:
	__slots__ = ['_n', '_m', '_vals']

	def __init__(self, vals):
		self._n = len(vals)
		self._m = 1 << (self._n - 1).bit_length()
		self._vals = [0] * self._m + vals

	def add_in_range(self, i, j, x):
		p = j + self._m
		t = 0
		i += self._m
		j += self._m
		while i < j:
			if i & 1:
				self._vals[i] += x
				i += 1
			if j & 1:
				j -= 1
				self._vals[j] += x
			i >>= 1
			j >>= 1
			t += self._vals[p]
			p >>= 1
		while p > 0:
			t += self._vals[p]
			p >>= 1
		return t

def main():
	n = int(input())
	s = input()
	c_index = {chr(97 + i): collections.deque() for i in range(26)}
	for i in range(n):
		c_index[s[i]].append(i)
	ans = left = index = 0
	right = n - 1
	index_increase = RangeAddList([0] * n)
	add = index_increase.add_in_range
	while index < n - 1:
		c_right = s[right]
		while c_index[s[left]] and c_index[s[left]][0] != left:
			left += 1
		c_left = s[left]
		if c_right != c_left:
			ind = c_index[c_right].popleft()
			c = add(left, ind, 1)
			ans += ind + c - index
		else:
			c_index[c_left].popleft()
			left += 1
		index += 1
		right -= 1
	print(ans)
main()


from sys import stdin
input = stdin.readline
global T, N

def get_index(char):
	return ord(char) - 97

def read(index):
	global T, N
	s = 0
	while index > 0:
		s += T[index]
		index -= index & -index
	return s

def update(index, val):
	global T, N
	while index <= N:
		T[index] += val
		index += index & -index
N = int(input())
S = input()[:N]
A = [[] for _ in range(26)]
for i in range(N):
	ind = get_index(S[i])
	A[ind].append(i + 1)
inds = [-1 for _ in range(26)]
T = [0 for _ in range(N + 1)]
ans = 0
for i in range(N - 1, -1, -1):
	idx = get_index(S[N - i - 1])
	x = A[idx][inds[idx]]
	inds[idx] -= 1
	ans += i + 1 - x - read(x)
	update(x + 1, -1)
print(ans)


from collections import defaultdict, deque
from heapq import heappush, heappop
from math import inf
ri = lambda : map(int, input().split())
ro = lambda : int(input())

class FW:

	def __init__(self, N):
		self.A = [0] * (N + 1)

	def add(self, idx, val):
		while idx < len(self.A):
			self.A[idx] += val
			idx += idx & -idx

	def qry(self, idx):
		sm = 0
		while idx > 0:
			sm += self.A[idx]
			idx -= idx & -idx
		return sm

def solve():
	n = ro()
	fw = FW(n)
	s = input()
	rev = s[::-1]
	cnt = defaultdict(int)
	indexes = defaultdict(list)
	for i in range(n):
		indexes[rev[i]].append(i)
	inv = []
	for i in range(n):
		inv.append(indexes[s[i]][cnt[s[i]]])
		cnt[s[i]] += 1
	ans = 0
	for i in range(n - 1, -1, -1):
		ans += fw.qry(inv[i] + 1)
		fw.add(inv[i] + 1, 1)
	print(ans)
t = 1
while t:
	t -= 1
	solve()


import sys
input = sys.stdin.readline
n = int(input())
S = input().strip()
LIST = [[] for i in range(26)]
for i in range(n):
	LIST[ord(S[i]) - 97].append(i)
LEN = n + 1
BIT = [0] * (LEN + 1)

def update(v, w):
	while v <= LEN:
		BIT[v] += w
		v += v & -v

def getvalue(v):
	ANS = 0
	while v != 0:
		ANS += BIT[v]
		v -= v & -v
	return ANS
ANS = 0
moji = [0] * 26
for i in range(n - 1, -1, -1):
	s = ord(S[i]) - 97
	x = LIST[s][moji[s]]
	ANS += x - getvalue(x + 1)
	moji[s] += 1
	update(x + 1, 1)
print(ANS)


count = 0

def merge(arr):
	if len(arr) == 1:
		return arr
	global count
	h = len(arr) // 2
	lt = merge(arr[:h])
	rt = merge(arr[h:])
	new_array = []
	(i, j) = (0, 0)
	while i < len(lt) and j < len(rt):
		if lt[i] <= rt[j]:
			new_array.append(lt[i])
			i += 1
		else:
			new_array.append(rt[j])
			count += len(lt) - i
			j += 1
	while i < len(lt):
		new_array.append(lt[i])
		i += 1
	while j < len(rt):
		new_array.append(rt[j])
		j += 1
	return new_array
n = int(input())
s = input()
visit = [0 for i in range(n)]
for i in range(26):
	ch = chr(97 + i)
	v = []
	for j in range(n):
		if ch == s[j]:
			v.append(j)
	m = len(v)
	for k in range(m):
		(x, y) = (v[k], n - 1 - v[m - 1 - k])
		visit[x] = y
count = 0
merge(visit)
print(count)


n = int(input())
s = list(str(input()))
t = list(reversed(s))
X = [[] for _ in range(26)]
Y = [[] for _ in range(26)]
for (i, c) in enumerate(s):
	j = ord(c) - ord('a')
	X[j].append(i)
for (i, c) in enumerate(t):
	j = ord(c) - ord('a')
	Y[j].append(i)
A = [-1] * n
for i in range(26):
	for (j, k) in zip(X[i], Y[i]):
		A[j] = k

class BIT:

	def __init__(self, n):
		self.n = n
		self.bit = [0] * (self.n + 1)

	def init(self, init_val):
		for (i, v) in enumerate(init_val):
			self.add(i, v)

	def add(self, i, x):
		i += 1
		while i <= self.n:
			self.bit[i] += x
			i += i & -i

	def sum(self, i, j):
		return self._sum(j) - self._sum(i)

	def _sum(self, i):
		res = 0
		while i > 0:
			res += self.bit[i]
			i -= i & -i
		return res

	def lower_bound(self, x):
		s = 0
		pos = 0
		depth = self.n.bit_length()
		v = 1 << depth
		for i in range(depth, -1, -1):
			k = pos + v
			if k <= self.n and s + self.bit[k] < x:
				s += self.bit[k]
				pos += v
			v >>= 1
		return pos
bit = BIT(max(A) + 1)
ans = 0
for a in A:
	ans += bit.sum(a + 1, bit.n)
	bit.add(a, 1)
print(ans)


from collections import defaultdict, deque
n = int(input())
s = input()

def mergesort(arr, n):
	temp_arr = [0] * n
	return _mergeSort(arr, temp_arr, 0, n - 1)

def _mergeSort(arr, temp_arr, left, right):
	inv_count = 0
	if left < right:
		mid = (left + right) // 2
		inv_count += _mergeSort(arr, temp_arr, left, mid)
		inv_count += _mergeSort(arr, temp_arr, mid + 1, right)
		inv_count += merge(arr, temp_arr, left, mid, right)
	return inv_count

def merge(arr, temp_arr, left, mid, right):
	i = left
	j = mid + 1
	k = left
	inv_count = 0
	while i <= mid and j <= right:
		if arr[i] <= arr[j]:
			temp_arr[k] = arr[i]
			k += 1
			i += 1
		else:
			temp_arr[k] = arr[j]
			inv_count += mid - i + 1
			k += 1
			j += 1
	while i <= mid:
		temp_arr[k] = arr[i]
		k += 1
		i += 1
	while j <= right:
		temp_arr[k] = arr[j]
		k += 1
		j += 1
	for i in range(left, right + 1):
		arr[i] = temp_arr[i]
	return inv_count
dic = defaultdict(lambda : deque())
rev = s[::-1]
for (i, char) in enumerate(rev):
	dic[char].append(i + 1)
arr = []
for i in s:
	arr.append(dic[i].popleft())
n = len(arr)
print(mergesort(arr, n))


import sys
input = sys.stdin.readline

class bit:

	def __init__(self, n):
		self.n = n + 1
		self.mx_p = 0
		while 1 << self.mx_p < self.n:
			self.mx_p += 1
		self.a = [0] * self.n
		self.tot = 0

	def add(self, idx, val):
		self.tot += val
		idx += 1
		while idx < self.n:
			self.a[idx] += val
			idx += idx & -idx

	def sum_prefix(self, idx):
		tot = 0
		idx += 1
		while idx > 0:
			tot += self.a[idx]
			idx -= idx & -idx
		return tot

	def sum(self, l, r):
		return self.sum_prefix(r) - self.sum_prefix(l - 1)

def inversions(a):
	tot = 0
	loc = [0] * len(a)
	for i in range(len(a)):
		loc[a[i]] = i
	bt = bit(len(a))
	for i in range(len(a) - 1, -1, -1):
		tot += bt.sum_prefix(loc[i])
		bt.add(loc[i], 1)
	return tot

def create_c(a, b):
	c = [0] * len(a)
	idx = {}
	positions = {}
	for i in range(len(b)):
		if b[i] in positions:
			positions[b[i]].append(i)
		else:
			positions[b[i]] = [i]
	for i in range(len(a)):
		if a[i] in idx:
			idx[a[i]] += 1
		else:
			idx[a[i]] = 0
		c[i] = positions[a[i]][idx[a[i]]]
	return c
n = int(input())
s = input().strip()
s_reversed = s[::-1]
print(inversions(create_c(s, s_reversed)))


n = int(input())
s = input()
target = s[::-1]
cnt = 0
mapping = {}
for i in range(n):
	if s[i] in mapping:
		mapping[s[i]].append(i)
	else:
		mapping[s[i]] = [i]
final = [-1] * n
for i in range(n - 1, -1, -1):
	final[i] = mapping[target[i]].pop(-1)

def combine(start1, end1, start2, end2):
	n1 = end1 - start1 + 1
	n2 = end2 - start2 + 1
	i = start1
	j = start2
	new = []
	cnt = 0
	while i <= end1 and j <= end2:
		if final[i] < final[j]:
			new.append(final[i])
			i += 1
		else:
			new.append(final[j])
			cnt += end1 - i + 1
			j += 1
	while i <= end1:
		new.append(final[i])
		i += 1
	while j <= end2:
		new.append(final[j])
		j += 1
	k = start1
	for i in new:
		final[k] = i
		k += 1
	return cnt

def count_inversions(start, end):
	if abs(start - end) <= 1:
		if final[start] <= final[end]:
			return 0
		(final[start], final[end]) = (final[end], final[start])
		return 1
	mid = (start + end) // 2
	num_left = count_inversions(start, mid)
	num_right = count_inversions(mid + 1, end)
	cnt = combine(start, mid, mid + 1, end)
	return num_left + num_right + cnt
print(count_inversions(0, n - 1))


def getNext(num):
	return num + (num & -num)

def getParent(num):
	return num - (num & -num)

def getSum(ftree, index):
	s = 0
	i = index
	while i > 0:
		s += ftree[i]
		i = getParent(i)
	return s
n = int(input())
s = input()
a = [[] for i in range(26)]
b = []
c = [0] * 26
for i in range(n):
	a[ord(s[i]) - 97].append(i + 1)
for i in range(n - 1, -1, -1):
	cr = ord(s[i]) - 97
	b.append(n + 1 - a[cr][c[cr]])
	c[cr] += 1
ls = [0] * (n + 1)
ans = 0
for i in b:
	ans += getSum(ls, i)
	ind = i
	while ind < n + 1:
		ls[ind] += 1
		ind = getNext(ind)
print(ans)


ans = 0

def count_inversion(arr):
	global ans
	if len(arr) <= 1:
		return arr
	mid = len(arr) // 2
	left = count_inversion(arr[:mid])
	right = count_inversion(arr[mid:])
	final = []
	i = 0
	j = 0
	while i < len(left) and j < len(right):
		if left[i] <= right[j]:
			final.append(left[i])
			i += 1
		else:
			final.append(right[j])
			ans += len(left) - i
			j += 1
	while i < len(left):
		final.append(left[i])
		i += 1
	while j < len(right):
		final.append(right[j])
		j += 1
	return final
n = int(input())
s = input()
position = [0] * n
for i in range(26):
	temp = []
	for j in range(len(s)):
		if s[j] == chr(ord('a') + i):
			temp.append(j)
	for j in range(len(temp)):
		curr = temp[j]
		dest = n - (temp[len(temp) - j - 1] + 1)
		position[curr] = dest
count_inversion(position)
print(ans)


(len, str) = (int(input()), input())
s = [ord(i) - ord('a') for i in str]
rev = s[::-1]
appe = [[] for i in range(ord('a'), ord('z') + 1)]
for (i, it) in enumerate(rev):
	appe[it].append(i)
(nxt, arr) = ([0 for i in range(ord('a'), ord('z') + 1)], [])
for it in s:
	arr.append(appe[it][nxt[it]] + 1)
	nxt[it] += 1

class fwt:

	def __init__(self, siz):
		self.maxn = siz + 50
		self.arr = [0 for i in range(self.maxn)]

	def Lowbit(self, val):
		return val & -val

	def Add(self, val, add=1):
		while val < self.maxn:
			self.arr[val] += add
			val += self.Lowbit(val)
		return self

	def Query(self, val):
		ans = 0
		while val > 0:
			ans -= self.arr[val]
			val -= self.Lowbit(val)
		val = self.maxn - 1
		while val > 0:
			ans += self.arr[val]
			val -= self.Lowbit(val)
		return ans
(cnt, fw) = (0, fwt(len))
for it in arr:
	cnt += fw.Query(it)
	fw.Add(it)
print(cnt)


class Bit:

	def __init__(self, n):
		self.size = n
		self.tree = [0] * (n + 1)
		self.depth = n.bit_length()

	def _sum(self, i):
		i += 1
		s = 0
		while i > 0:
			s += self.tree[i]
			i -= i & -i
		return s

	def sum(self, l, r):
		return self._sum(r - 1) - self._sum(l - 1)

	def add(self, i, x):
		i += 1
		while i <= self.size:
			self.tree[i] += x
			i += i & -i

	def lower_bound(self, x):
		sum_ = 0
		pos = 0
		for i in range(self.depth, -1, -1):
			k = pos + (1 << i)
			if k <= self.size and sum_ + self.tree[k] < x:
				sum_ += self.tree[k]
				pos += 1 << i
		return (pos, sum_)

	def get_less_than_x_cnt(self, x):
		(lb_pos, lb_sum) = self.lower_bound(x)
		return lb_pos - 1

	def get_less_than_and_x_cnt(self, x):
		(lb_pos, lb_sum) = self.lower_bound(x + 1)
		return lb_pos - 1

	def get_more_than_x_cnt(self, x):
		return self.size - self.get_less_than_and_x_cnt(x)
from collections import deque
n = int(input())
s = input()
sr = s[::-1]
bit = Bit(n)
alp_d = {chr(ord('a') + i): deque() for i in range(26)}
for (i, si) in enumerate(s):
	alp_d[si].append(i)
ans = 0
for i in range(n):
	si = sr[i]
	near_i = alp_d[si].popleft()
	moved = bit.sum(near_i, n)
	d = near_i - i + moved
	bit.add(near_i, 1)
	ans += d
print(ans)


import collections

class BIT:

	def __init__(self, n):
		self.n = n
		self.tree = [0] * (n + 1)

	def update(self, x, v):
		while x <= self.n:
			self.tree[x] += v
			x += x & -x

	def query(self, x):
		ans = 0
		while x:
			ans += self.tree[x]
			x -= x & -x
		return ans
n = int(input())
s = list(input())
rs = list(reversed(s))
dic = collections.defaultdict(collections.deque)
bit = BIT(n + 1)
for (i, c) in enumerate(s):
	dic[c].append(i)
ans = 0
for (i, c) in enumerate(rs):
	idx = dic[c].popleft()
	inc = bit.query(n - idx)
	ans += idx - i + inc
	bit.update(n - idx + 1, 1)
print(ans)


N = int(input())
S = input()
dic = {}
for (i, s) in enumerate(S):
	if s in dic:
		dic[s].append(i)
	else:
		dic[s] = [i]
X = list(range(N - 1, -1, -1))
for (c, idcs) in dic.items():
	for (p, q) in zip(idcs, reversed(idcs)):
		X[p] = N - 1 - q

class BIT:

	def __init__(self, N):
		self.N = N
		self.T = [0] * (N + 1)

	def add(self, i, x):
		i += 1
		while i <= self.N:
			self.T[i] += x
			i += i & -i

	def _sum(self, i):
		ret = 0
		while i > 0:
			ret += self.T[i]
			i ^= i & -i
		return ret

	def sum(self, l, r):
		return self._sum(r) - self._sum(l)

	def lower_bound(self, w):
		if w <= 0:
			return 0
		x = 0
		k = 1 << self.N.bit_length()
		while k:
			if x + k <= self.N and self.T[x + k] < w:
				w -= self.t[x + k]
				x += k
				k >>= 1
		return x + 1
b = BIT(N)
ans = 0
for (i, x) in enumerate(X):
	ans += i - b._sum(x + 1)
	b.add(x, 1)
print(ans)


import sys
import traceback
from bisect import bisect_left, bisect_right, insort
from itertools import chain, repeat, starmap
from math import log
from operator import add, eq, ne, gt, ge, lt, le, iadd
from textwrap import dedent
try:
	from collections.abc import Sequence, MutableSequence
except ImportError:
	from collections import Sequence, MutableSequence
from functools import wraps
from sys import hexversion
if hexversion < 50331648:
	try:
		from _thread import get_ident
	except ImportError:
		from _dummy_thread import get_ident
else:
	from functools import reduce
	try:
		from _thread import get_ident
	except ImportError:
		from _dummy_thread import get_ident

def recursive_repr(fillvalue='...'):

	def decorating_function(user_function):
		repr_running = set()

		@wraps(user_function)
		def wrapper(self):
			key = (id(self), get_ident())
			if key in repr_running:
				return fillvalue
			repr_running.add(key)
			try:
				result = user_function(self)
			finally:
				repr_running.discard(key)
			return result
		return wrapper
	return decorating_function

class SortedList(MutableSequence):
	DEFAULT_LOAD_FACTOR = 1000

	def __init__(self, iterable=None, key=None):
		assert key is None
		self._len = 0
		self._load = self.DEFAULT_LOAD_FACTOR
		self._lists = []
		self._maxes = []
		self._index = []
		self._offset = 0
		if iterable is not None:
			self._update(iterable)

	def __new__(cls, iterable=None, key=None):
		if key is None:
			return object.__new__(cls)
		elif cls is SortedList:
			return object.__new__(SortedKeyList)
		else:
			raise TypeError('inherit SortedKeyList for key argument')

	@property
	def key(self):
		return None

	def _reset(self, load):
		values = reduce(iadd, self._lists, [])
		self._clear()
		self._load = load
		self._update(values)

	def clear(self):
		self._len = 0
		del self._lists[:]
		del self._maxes[:]
		del self._index[:]
		self._offset = 0
	_clear = clear

	def add(self, value):
		_lists = self._lists
		_maxes = self._maxes
		if _maxes:
			pos = bisect_right(_maxes, value)
			if pos == len(_maxes):
				pos -= 1
				_lists[pos].append(value)
				_maxes[pos] = value
			else:
				insort(_lists[pos], value)
			self._expand(pos)
		else:
			_lists.append([value])
			_maxes.append(value)
		self._len += 1

	def _expand(self, pos):
		_load = self._load
		_lists = self._lists
		_index = self._index
		if len(_lists[pos]) > _load << 1:
			_maxes = self._maxes
			_lists_pos = _lists[pos]
			half = _lists_pos[_load:]
			del _lists_pos[_load:]
			_maxes[pos] = _lists_pos[-1]
			_lists.insert(pos + 1, half)
			_maxes.insert(pos + 1, half[-1])
			del _index[:]
		elif _index:
			child = self._offset + pos
			while child:
				_index[child] += 1
				child = child - 1 >> 1
			_index[0] += 1

	def update(self, iterable):
		_lists = self._lists
		_maxes = self._maxes
		values = sorted(iterable)
		if _maxes:
			if len(values) * 4 >= self._len:
				values.extend(chain.from_iterable(_lists))
				values.sort()
				self._clear()
			else:
				_add = self.add
				for val in values:
					_add(val)
				return
		_load = self._load
		_lists.extend((values[pos:pos + _load] for pos in range(0, len(values), _load)))
		_maxes.extend((sublist[-1] for sublist in _lists))
		self._len = len(values)
		del self._index[:]
	_update = update

	def __contains__(self, value):
		_maxes = self._maxes
		if not _maxes:
			return False
		pos = bisect_left(_maxes, value)
		if pos == len(_maxes):
			return False
		_lists = self._lists
		idx = bisect_left(_lists[pos], value)
		return _lists[pos][idx] == value

	def discard(self, value):
		_maxes = self._maxes
		if not _maxes:
			return
		pos = bisect_left(_maxes, value)
		if pos == len(_maxes):
			return
		_lists = self._lists
		idx = bisect_left(_lists[pos], value)
		if _lists[pos][idx] == value:
			self._delete(pos, idx)

	def remove(self, value):
		_maxes = self._maxes
		if not _maxes:
			raise ValueError('{0!r} not in list'.format(value))
		pos = bisect_left(_maxes, value)
		if pos == len(_maxes):
			raise ValueError('{0!r} not in list'.format(value))
		_lists = self._lists
		idx = bisect_left(_lists[pos], value)
		if _lists[pos][idx] == value:
			self._delete(pos, idx)
		else:
			raise ValueError('{0!r} not in list'.format(value))

	def _delete(self, pos, idx):
		_lists = self._lists
		_maxes = self._maxes
		_index = self._index
		_lists_pos = _lists[pos]
		del _lists_pos[idx]
		self._len -= 1
		len_lists_pos = len(_lists_pos)
		if len_lists_pos > self._load >> 1:
			_maxes[pos] = _lists_pos[-1]
			if _index:
				child = self._offset + pos
				while child > 0:
					_index[child] -= 1
					child = child - 1 >> 1
				_index[0] -= 1
		elif len(_lists) > 1:
			if not pos:
				pos += 1
			prev = pos - 1
			_lists[prev].extend(_lists[pos])
			_maxes[prev] = _lists[prev][-1]
			del _lists[pos]
			del _maxes[pos]
			del _index[:]
			self._expand(prev)
		elif len_lists_pos:
			_maxes[pos] = _lists_pos[-1]
		else:
			del _lists[pos]
			del _maxes[pos]
			del _index[:]

	def _loc(self, pos, idx):
		if not pos:
			return idx
		_index = self._index
		if not _index:
			self._build_index()
		total = 0
		pos += self._offset
		while pos:
			if not pos & 1:
				total += _index[pos - 1]
			pos = pos - 1 >> 1
		return total + idx

	def _pos(self, idx):
		if idx < 0:
			last_len = len(self._lists[-1])
			if -idx <= last_len:
				return (len(self._lists) - 1, last_len + idx)
			idx += self._len
			if idx < 0:
				raise IndexError('list index out of range')
		elif idx >= self._len:
			raise IndexError('list index out of range')
		if idx < len(self._lists[0]):
			return (0, idx)
		_index = self._index
		if not _index:
			self._build_index()
		pos = 0
		child = 1
		len_index = len(_index)
		while child < len_index:
			index_child = _index[child]
			if idx < index_child:
				pos = child
			else:
				idx -= index_child
				pos = child + 1
			child = (pos << 1) + 1
		return (pos - self._offset, idx)

	def _build_index(self):
		row0 = list(map(len, self._lists))
		if len(row0) == 1:
			self._index[:] = row0
			self._offset = 0
			return
		head = iter(row0)
		tail = iter(head)
		row1 = list(starmap(add, list(zip(head, tail))))
		if len(row0) & 1:
			row1.append(row0[-1])
		if len(row1) == 1:
			self._index[:] = row1 + row0
			self._offset = 1
			return
		size = 2 ** (int(log(len(row1) - 1, 2)) + 1)
		row1.extend(repeat(0, size - len(row1)))
		tree = [row0, row1]
		while len(tree[-1]) > 1:
			head = iter(tree[-1])
			tail = iter(head)
			row = list(starmap(add, list(zip(head, tail))))
			tree.append(row)
		reduce(iadd, reversed(tree), self._index)
		self._offset = size * 2 - 1

	def __delitem__(self, index):
		if isinstance(index, slice):
			(start, stop, step) = index.indices(self._len)
			if step == 1 and start < stop:
				if start == 0 and stop == self._len:
					return self._clear()
				elif self._len <= 8 * (stop - start):
					values = self._getitem(slice(None, start))
					if stop < self._len:
						values += self._getitem(slice(stop, None))
					self._clear()
					return self._update(values)
			indices = list(range(start, stop, step))
			if step > 0:
				indices = reversed(indices)
			(_pos, _delete) = (self._pos, self._delete)
			for index in indices:
				(pos, idx) = _pos(index)
				_delete(pos, idx)
		else:
			(pos, idx) = self._pos(index)
			self._delete(pos, idx)

	def __getitem__(self, index):
		_lists = self._lists
		if isinstance(index, slice):
			(start, stop, step) = index.indices(self._len)
			if step == 1 and start < stop:
				if start == 0 and stop == self._len:
					return reduce(iadd, self._lists, [])
				(start_pos, start_idx) = self._pos(start)
				start_list = _lists[start_pos]
				stop_idx = start_idx + stop - start
				if len(start_list) >= stop_idx:
					return start_list[start_idx:stop_idx]
				if stop == self._len:
					stop_pos = len(_lists) - 1
					stop_idx = len(_lists[stop_pos])
				else:
					(stop_pos, stop_idx) = self._pos(stop)
				prefix = _lists[start_pos][start_idx:]
				middle = _lists[start_pos + 1:stop_pos]
				result = reduce(iadd, middle, prefix)
				result += _lists[stop_pos][:stop_idx]
				return result
			if step == -1 and start > stop:
				result = self._getitem(slice(stop + 1, start + 1))
				result.reverse()
				return result
			indices = list(range(start, stop, step))
			return list((self._getitem(index) for index in indices))
		else:
			if self._len:
				if index == 0:
					return _lists[0][0]
				elif index == -1:
					return _lists[-1][-1]
			else:
				raise IndexError('list index out of range')
			if 0 <= index < len(_lists[0]):
				return _lists[0][index]
			len_last = len(_lists[-1])
			if -len_last < index < 0:
				return _lists[-1][len_last + index]
			(pos, idx) = self._pos(index)
			return _lists[pos][idx]
	_getitem = __getitem__

	def __setitem__(self, index, value):
		message = 'use ``del sl[index]`` and ``sl.add(value)`` instead'
		raise NotImplementedError(message)

	def __iter__(self):
		return chain.from_iterable(self._lists)

	def __reversed__(self):
		return chain.from_iterable(list(map(reversed, reversed(self._lists))))

	def reverse(self):
		raise NotImplementedError('use ``reversed(sl)`` instead')

	def islice(self, start=None, stop=None, reverse=False):
		_len = self._len
		if not _len:
			return iter(())
		(start, stop, _) = slice(start, stop).indices(self._len)
		if start >= stop:
			return iter(())
		_pos = self._pos
		(min_pos, min_idx) = _pos(start)
		if stop == _len:
			max_pos = len(self._lists) - 1
			max_idx = len(self._lists[-1])
		else:
			(max_pos, max_idx) = _pos(stop)
		return self._islice(min_pos, min_idx, max_pos, max_idx, reverse)

	def _islice(self, min_pos, min_idx, max_pos, max_idx, reverse):
		_lists = self._lists
		if min_pos > max_pos:
			return iter(())
		if min_pos == max_pos:
			if reverse:
				indices = reversed(list(range(min_idx, max_idx)))
				return list(map(_lists[min_pos].__getitem__, indices))
			indices = list(range(min_idx, max_idx))
			return list(map(_lists[min_pos].__getitem__, indices))
		next_pos = min_pos + 1
		if next_pos == max_pos:
			if reverse:
				min_indices = list(range(min_idx, len(_lists[min_pos])))
				max_indices = list(range(max_idx))
				return chain(list(map(_lists[max_pos].__getitem__, reversed(max_indices))), list(map(_lists[min_pos].__getitem__, reversed(min_indices))))
			min_indices = list(range(min_idx, len(_lists[min_pos])))
			max_indices = list(range(max_idx))
			return chain(list(map(_lists[min_pos].__getitem__, min_indices)), list(map(_lists[max_pos].__getitem__, max_indices)))
		if reverse:
			min_indices = list(range(min_idx, len(_lists[min_pos])))
			sublist_indices = list(range(next_pos, max_pos))
			sublists = list(map(_lists.__getitem__, reversed(sublist_indices)))
			max_indices = list(range(max_idx))
			return chain(list(map(_lists[max_pos].__getitem__, reversed(max_indices))), chain.from_iterable(list(map(reversed, sublists))), list(map(_lists[min_pos].__getitem__, reversed(min_indices))))
		min_indices = list(range(min_idx, len(_lists[min_pos])))
		sublist_indices = list(range(next_pos, max_pos))
		sublists = list(map(_lists.__getitem__, sublist_indices))
		max_indices = list(range(max_idx))
		return chain(list(map(_lists[min_pos].__getitem__, min_indices)), chain.from_iterable(sublists), list(map(_lists[max_pos].__getitem__, max_indices)))

	def irange(self, minimum=None, maximum=None, inclusive=(True, True), reverse=False):
		_maxes = self._maxes
		if not _maxes:
			return iter(())
		_lists = self._lists
		if minimum is None:
			min_pos = 0
			min_idx = 0
		elif inclusive[0]:
			min_pos = bisect_left(_maxes, minimum)
			if min_pos == len(_maxes):
				return iter(())
			min_idx = bisect_left(_lists[min_pos], minimum)
		else:
			min_pos = bisect_right(_maxes, minimum)
			if min_pos == len(_maxes):
				return iter(())
			min_idx = bisect_right(_lists[min_pos], minimum)
		if maximum is None:
			max_pos = len(_maxes) - 1
			max_idx = len(_lists[max_pos])
		elif inclusive[1]:
			max_pos = bisect_right(_maxes, maximum)
			if max_pos == len(_maxes):
				max_pos -= 1
				max_idx = len(_lists[max_pos])
			else:
				max_idx = bisect_right(_lists[max_pos], maximum)
		else:
			max_pos = bisect_left(_maxes, maximum)
			if max_pos == len(_maxes):
				max_pos -= 1
				max_idx = len(_lists[max_pos])
			else:
				max_idx = bisect_left(_lists[max_pos], maximum)
		return self._islice(min_pos, min_idx, max_pos, max_idx, reverse)

	def __len__(self):
		return self._len

	def bisect_left(self, value):
		_maxes = self._maxes
		if not _maxes:
			return 0
		pos = bisect_left(_maxes, value)
		if pos == len(_maxes):
			return self._len
		idx = bisect_left(self._lists[pos], value)
		return self._loc(pos, idx)

	def bisect_right(self, value):
		_maxes = self._maxes
		if not _maxes:
			return 0
		pos = bisect_right(_maxes, value)
		if pos == len(_maxes):
			return self._len
		idx = bisect_right(self._lists[pos], value)
		return self._loc(pos, idx)
	bisect = bisect_right
	_bisect_right = bisect_right

	def count(self, value):
		_maxes = self._maxes
		if not _maxes:
			return 0
		pos_left = bisect_left(_maxes, value)
		if pos_left == len(_maxes):
			return 0
		_lists = self._lists
		idx_left = bisect_left(_lists[pos_left], value)
		pos_right = bisect_right(_maxes, value)
		if pos_right == len(_maxes):
			return self._len - self._loc(pos_left, idx_left)
		idx_right = bisect_right(_lists[pos_right], value)
		if pos_left == pos_right:
			return idx_right - idx_left
		right = self._loc(pos_right, idx_right)
		left = self._loc(pos_left, idx_left)
		return right - left

	def copy(self):
		return self.__class__(self)
	__copy__ = copy

	def append(self, value):
		raise NotImplementedError('use ``sl.add(value)`` instead')

	def extend(self, values):
		raise NotImplementedError('use ``sl.update(values)`` instead')

	def insert(self, index, value):
		raise NotImplementedError('use ``sl.add(value)`` instead')

	def pop(self, index=-1):
		if not self._len:
			raise IndexError('pop index out of range')
		_lists = self._lists
		if index == 0:
			val = _lists[0][0]
			self._delete(0, 0)
			return val
		if index == -1:
			pos = len(_lists) - 1
			loc = len(_lists[pos]) - 1
			val = _lists[pos][loc]
			self._delete(pos, loc)
			return val
		if 0 <= index < len(_lists[0]):
			val = _lists[0][index]
			self._delete(0, index)
			return val
		len_last = len(_lists[-1])
		if -len_last < index < 0:
			pos = len(_lists) - 1
			loc = len_last + index
			val = _lists[pos][loc]
			self._delete(pos, loc)
			return val
		(pos, idx) = self._pos(index)
		val = _lists[pos][idx]
		self._delete(pos, idx)
		return val

	def index(self, value, start=None, stop=None):
		_len = self._len
		if not _len:
			raise ValueError('{0!r} is not in list'.format(value))
		if start is None:
			start = 0
		if start < 0:
			start += _len
		if start < 0:
			start = 0
		if stop is None:
			stop = _len
		if stop < 0:
			stop += _len
		if stop > _len:
			stop = _len
		if stop <= start:
			raise ValueError('{0!r} is not in list'.format(value))
		_maxes = self._maxes
		pos_left = bisect_left(_maxes, value)
		if pos_left == len(_maxes):
			raise ValueError('{0!r} is not in list'.format(value))
		_lists = self._lists
		idx_left = bisect_left(_lists[pos_left], value)
		if _lists[pos_left][idx_left] != value:
			raise ValueError('{0!r} is not in list'.format(value))
		stop -= 1
		left = self._loc(pos_left, idx_left)
		if start <= left:
			if left <= stop:
				return left
		else:
			right = self._bisect_right(value) - 1
			if start <= right:
				return start
		raise ValueError('{0!r} is not in list'.format(value))

	def __add__(self, other):
		values = reduce(iadd, self._lists, [])
		values.extend(other)
		return self.__class__(values)
	__radd__ = __add__

	def __iadd__(self, other):
		self._update(other)
		return self

	def __mul__(self, num):
		values = reduce(iadd, self._lists, []) * num
		return self.__class__(values)
	__rmul__ = __mul__

	def __imul__(self, num):
		values = reduce(iadd, self._lists, []) * num
		self._clear()
		self._update(values)
		return self

	def __make_cmp(seq_op, symbol, doc):

		def comparer(self, other):
			if not isinstance(other, Sequence):
				return NotImplemented
			self_len = self._len
			len_other = len(other)
			if self_len != len_other:
				if seq_op is eq:
					return False
				if seq_op is ne:
					return True
			for (alpha, beta) in zip(self, other):
				if alpha != beta:
					return seq_op(alpha, beta)
			return seq_op(self_len, len_other)
		seq_op_name = seq_op.__name__
		comparer.__name__ = '__{0}__'.format(seq_op_name)
		doc_str = 'Return true if and only if sorted list is {0} `other`.\n\n        ``sl.__{1}__(other)`` <==> ``sl {2} other``\n\n        Comparisons use lexicographical order as with sequences.\n\n        Runtime complexity: `O(n)`\n\n        :param other: `other` sequence\n        :return: true if sorted list is {0} `other`\n\n        '
		comparer.__doc__ = dedent(doc_str.format(doc, seq_op_name, symbol))
		return comparer
	__eq__ = __make_cmp(eq, '==', 'equal to')
	__ne__ = __make_cmp(ne, '!=', 'not equal to')
	__lt__ = __make_cmp(lt, '<', 'less than')
	__gt__ = __make_cmp(gt, '>', 'greater than')
	__le__ = __make_cmp(le, '<=', 'less than or equal to')
	__ge__ = __make_cmp(ge, '>=', 'greater than or equal to')
	__make_cmp = staticmethod(__make_cmp)

	def __reduce__(self):
		values = reduce(iadd, self._lists, [])
		return (type(self), (values,))

	@recursive_repr()
	def __repr__(self):
		return '{0}({1!r})'.format(type(self).__name__, list(self))

	def _check(self):
		try:
			assert self._load >= 4
			assert len(self._maxes) == len(self._lists)
			assert self._len == sum((len(sublist) for sublist in self._lists))
			for sublist in self._lists:
				for pos in range(1, len(sublist)):
					assert sublist[pos - 1] <= sublist[pos]
			for pos in range(1, len(self._lists)):
				assert self._lists[pos - 1][-1] <= self._lists[pos][0]
			for pos in range(len(self._maxes)):
				assert self._maxes[pos] == self._lists[pos][-1]
			double = self._load << 1
			assert all((len(sublist) <= double for sublist in self._lists))
			half = self._load >> 1
			for pos in range(0, len(self._lists) - 1):
				assert len(self._lists[pos]) >= half
			if self._index:
				assert self._len == self._index[0]
				assert len(self._index) == self._offset + len(self._lists)
				for pos in range(len(self._lists)):
					leaf = self._index[self._offset + pos]
					assert leaf == len(self._lists[pos])
				for pos in range(self._offset):
					child = (pos << 1) + 1
					if child >= len(self._index):
						assert self._index[pos] == 0
					elif child + 1 == len(self._index):
						assert self._index[pos] == self._index[child]
					else:
						child_sum = self._index[child] + self._index[child + 1]
						assert child_sum == self._index[pos]
		except:
			traceback.print_exc(file=sys.stdout)
			print('len', self._len)
			print('load', self._load)
			print('offset', self._offset)
			print('len_index', len(self._index))
			print('index', self._index)
			print('len_maxes', len(self._maxes))
			print('maxes', self._maxes)
			print('len_lists', len(self._lists))
			print('lists', self._lists)
			raise
n = int(input())
s = input()
ss = set(s)
p = {x: [] for x in ss}
pi = {x: 0 for x in ss}
for (i, c) in enumerate(s):
	p[c].append(i)
ans = 0
sl = SortedList()
for (i, c) in enumerate(reversed(s)):
	ppic = p[c][pi[c]]
	ans += ppic - i
	ans += len(sl) - sl.bisect(ppic)
	sl.add(ppic)
	pi[c] += 1
print(ans)


from __future__ import division, print_function
from fractions import Fraction
import sys
import os
from io import BytesIO, IOBase
from itertools import *
import bisect
from heapq import *
from math import ceil, floor
from copy import *
from collections import deque, defaultdict
from collections import Counter as counter
from itertools import combinations
from itertools import permutations as permutate
from bisect import bisect_left as bl
from operator import *
from bisect import bisect_right as br
from bisect import bisect
BUFSIZE = 8192
from sys import stderr

class FastIO(IOBase):
	newlines = 0

	def __init__(self, file):
		self._fd = file.fileno()
		self.buffer = BytesIO()
		self.writable = 'x' in file.mode or 'r' not in file.mode
		self.write = self.buffer.write if self.writable else None

	def read(self):
		while True:
			b = os.read(self._fd, max(os.fstat(self._fd).st_size, BUFSIZE))
			if not b:
				break
			ptr = self.buffer.tell()
			(self.buffer.seek(0, 2), self.buffer.write(b), self.buffer.seek(ptr))
		self.newlines = 0
		return self.buffer.read()

	def readline(self):
		while self.newlines == 0:
			b = os.read(self._fd, max(os.fstat(self._fd).st_size, BUFSIZE))
			self.newlines = b.count(b'\n') + (not b)
			ptr = self.buffer.tell()
			(self.buffer.seek(0, 2), self.buffer.write(b), self.buffer.seek(ptr))
		self.newlines -= 1
		return self.buffer.readline()

	def flush(self):
		if self.writable:
			os.write(self._fd, self.buffer.getvalue())
			(self.buffer.truncate(0), self.buffer.seek(0))

class IOWrapper(IOBase):

	def __init__(self, file):
		self.buffer = FastIO(file)
		self.flush = self.buffer.flush
		self.writable = self.buffer.writable
		self.write = lambda s: self.buffer.write(s.encode('ascii'))
		self.read = lambda : self.buffer.read().decode('ascii')
		self.readline = lambda : self.buffer.readline().decode('ascii')

def print(*args, **kwargs):
	(sep, file) = (kwargs.pop('sep', ' '), kwargs.pop('file', sys.stdout))
	at_start = True
	for x in args:
		if not at_start:
			file.write(sep)
		file.write(str(x))
		at_start = False
	file.write(kwargs.pop('end', '\n'))
	if kwargs.pop('flush', False):
		file.flush()
if sys.version_info[0] < 3:
	(sys.stdin, sys.stdout) = (FastIO(sys.stdin), FastIO(sys.stdout))
else:
	(sys.stdin, sys.stdout) = (IOWrapper(sys.stdin), IOWrapper(sys.stdout))
from types import GeneratorType

def iterative(f, stack=[]):

	def wrapped_func(*args, **kwargs):
		if stack:
			return f(*args, **kwargs)
		to = f(*args, **kwargs)
		while True:
			if type(to) is GeneratorType:
				stack.append(to)
				to = next(to)
				continue
			stack.pop()
			if not stack:
				break
			to = stack[-1].send(to)
		return to
	return wrapped_func
mod = 1000000007

def inp():
	return sys.stdin.readline().rstrip('\r\n')

def out(var):
	sys.stdout.write(str(var))

def lis():
	return list(map(int, inp().split()))

def stringlis():
	return list(map(str, inp().split()))

def sep():
	return map(int, inp().split())

def strsep():
	return map(str, inp().split())

def fsep():
	return map(float, inp().split())

def nextline():
	out('\n')

def testcase(t):
	for p in range(t):
		solve()

def pow(x, y, p):
	res = 1
	x = x % p
	if x == 0:
		return 0
	while y > 0:
		if y & 1 == 1:
			res = res * x % p
		y = y >> 1
		x = x * x % p
	return res
from functools import reduce

def factors(n):
	return set(reduce(list.__add__, ([i, n // i] for i in range(1, int(n ** 0.5) + 1) if n % i == 0)))

def gcd(a, b):
	if a == b:
		return a
	while b > 0:
		(a, b) = (b, a % b)
	return a

def comb(n, r):
	if n < r:
		return 0
	else:
		return fac[n] * (finv[r] * finv[n - r] % mod) % mod

def prefix_sum(ar):
	return list(accumulate(ar))

def suffix_sum(ar):
	return list(accumulate(ar[::-1]))[::-1]

def N():
	return int(inp())
from collections import defaultdict
sys.setrecursionlimit(300000)

def numberOfSetBits(i):
	i = i - (i >> 1 & 1431655765)
	i = (i & 858993459) + (i >> 2 & 858993459)
	return ((i + (i >> 4) & 252645135) * 16843009 & 4294967295) >> 24
from math import factorial as f

def solve():

	def mergeSort(arr, n):
		temp_arr = [0] * n
		return _mergeSort(arr, temp_arr, 0, n - 1)

	def _mergeSort(arr, temp_arr, left, right):
		inv_count = 0
		if left < right:
			mid = (left + right) // 2
			inv_count += _mergeSort(arr, temp_arr, left, mid)
			inv_count += _mergeSort(arr, temp_arr, mid + 1, right)
			inv_count += merge(arr, temp_arr, left, mid, right)
		return inv_count

	def merge(arr, temp_arr, left, mid, right):
		i = left
		j = mid + 1
		k = left
		inv_count = 0
		while i <= mid and j <= right:
			if arr[i] <= arr[j]:
				temp_arr[k] = arr[i]
				k += 1
				i += 1
			else:
				temp_arr[k] = arr[j]
				inv_count += mid - i + 1
				k += 1
				j += 1
		while i <= mid:
			temp_arr[k] = arr[i]
			k += 1
			i += 1
		while j <= right:
			temp_arr[k] = arr[j]
			k += 1
			j += 1
		for loop_var in range(left, right + 1):
			arr[loop_var] = temp_arr[loop_var]
		return inv_count
	n = N()
	s = inp()
	revs = s[::-1]
	d2 = defaultdict(deque)
	for i in range(n):
		d2[revs[i]].append(i)
	arr = [0] * n
	for i in range(n):
		t = d2[s[i]].popleft()
		arr[i] = t
	result = mergeSort(arr, n)
	print(result)
solve()


(len, str) = (int(input()), input())
s = [ord(i) - ord('a') for i in str]
rev = s[::-1]
appe = [[] for i in range(ord('a'), ord('z') + 1)]
for (i, it) in enumerate(rev):
	appe[it].append(i)
(nxt, arr) = ([0 for i in range(ord('a'), ord('z') + 1)], [])
for it in s:
	arr.append(appe[it][nxt[it]] + 1)
	nxt[it] += 1
maxn = len + 50
fwt = [0 for i in range(maxn)]

def Add(val):
	while val < maxn:
		fwt[val] += 1
		val += val & -val

def Query(val):
	ans = 0
	while val > 0:
		ans -= fwt[val]
		val -= val & -val
	val = maxn - 1
	while val > 0:
		ans += fwt[val]
		val -= val & -val
	return ans
cnt = 0
for it in arr:
	cnt += Query(it)
	Add(it)
print(cnt)


mod = 1000000007
eps = 10 ** (-9)

def main():
	import sys
	input = sys.stdin.readline

	class Bit:

		def __init__(self, n):
			self.size = n
			self.tree = [0] * (n + 1)

		def sum(self, i):
			s = 0
			while i > 0:
				s += self.tree[i]
				i -= i & -i
			return s

		def add(self, i, x):
			while i <= self.size:
				self.tree[i] += x
				i += i & -i

		def lower_bound(self, w):
			if w <= 0:
				return 0
			x = 0
			k = 1 << self.size.bit_length() - 1
			while k:
				if x + k <= self.size and self.tree[x + k] < w:
					w -= self.tree[x + k]
					x += k
				k >>= 1
			return x + 1
	N = int(input())
	S = input().rstrip('\n')
	S_rev = S[::-1]
	idx = [[] for _ in range(26)]
	for (i, s) in enumerate(S):
		idx[ord(s) - 97].append(i)
	cnt = [0] * 26
	A = [0] * N
	for (i, s) in enumerate(S_rev):
		si = ord(s) - 97
		A[idx[si][cnt[si]]] = i
		cnt[si] += 1
	a2i = {a: i + 1 for (i, a) in enumerate(A)}
	bit = Bit(N)
	ans = 0
	for a in range(N - 1, -1, -1):
		ans += bit.sum(a2i[a])
		bit.add(a2i[a], 1)
	print(ans)
main()


from sys import stdin, stdout

def string_reversal(n, s):
	a = [[] for _ in range(26)]
	bit_a = [0] * (n + 1)
	t = n
	res = 0
	for i in range(len(s)):
		bit_update(bit_a, i, 1)
		a[ord(s[i]) - ord('a')].append(i)
	for i in range(len(s)):
		j = a[ord(s[i]) - ord('a')].pop()
		res += t - bit_get(bit_a, j)
		bit_update(bit_a, j, -1)
		t -= 1
	return res

def bit_update(bit_a, i, delta):
	i += 1
	while i < len(bit_a):
		bit_a[i] += delta
		i += i & -i

def bit_get(bit_a, i):
	i += 1
	v = 0
	while i > 0:
		v += bit_a[i]
		i -= i & -i
	return v
n = int(stdin.readline())
s = stdin.readline().strip()
r = string_reversal(n, s)
print(r)


def merge(a, b):
	i = 0
	j = 0
	c = 0
	ans = []
	while i < len(a) and j < len(b):
		if a[i] < b[j]:
			ans.append(a[i])
			i += 1
		else:
			ans.append(b[j])
			c += len(a) - i
			j += 1
	ans += a[i:]
	ans += b[j:]
	return (ans, c)

def mergesort(a):
	if len(a) == 1:
		return (a, 0)
	mid = len(a) // 2
	(left, left_inversion) = mergesort(a[:mid])
	(right, right_inversion) = mergesort(a[mid:])
	(m, c) = merge(left, right)
	c += left_inversion + right_inversion
	return (m, c)
n = int(input())
s = input()
a = [0] * n
ind = [[] for i in range(26)]
for i in range(n):
	ind[ord(s[i]) - ord('a')].append(n - i)
for i in range(n):
	a[i] = ind[ord(s[i]) - ord('a')].pop()
(m, c) = mergesort(a)
print(c)


import sys
from array import array
import typing as Tp

def input():
	return sys.stdin.buffer.readline().decode('utf-8')

def output(*args):
	sys.stdout.buffer.write(('\n'.join(map(str, args)) + '\n').encode('utf-8'))
T = Tp.TypeVar('T')

class FenwickSum(Tp.Generic[T]):
	__slots__ = ['nodes', 'size', 'unit']

	def __init__(self, size: int, default: T, unit: T):
		self.nodes = [default] * (size + 1)
		self.size = size + 1
		self.unit = unit

	def add(self, index: int, value: T):
		while index < self.size:
			self.nodes[index] += value
			index += index & -index

	def sum(self, right: int) -> T:
		result = self.unit
		while right:
			result += self.nodes[right]
			right -= right & -right
		return result

	def lower_bound(self, value: T) -> int:
		(k, result) = (1 << self.size.bit_length() - 1, 0)
		while k:
			if k + result < self.size and self.nodes[k + result] < value:
				value -= self.nodes[k + result]
				result += k
			k >>= 1
		return result + 1

def main():
	from collections import defaultdict
	n = int(input())
	s = '*' + input().rstrip()
	bit = FenwickSum(n + 10, 0, 0)
	dd: Tp.DefaultDict[str, Tp.List[int]] = defaultdict(list)
	ans = 0
	for i in range(n, 0, -1):
		dd[s[i]].append(i)
	for i in range(1, n + 1):
		t = dd[s[-i]].pop()
		ans += t - bit.sum(t) - 1
		bit.add(t, 1)
	print(ans)
main()


def mergesort(l, n):
	if n == 1:
		return (l, 0)
	else:
		(a, ans1) = mergesort(l[0:n // 2], n // 2)
		(b, ans2) = mergesort(l[n // 2:], n - n // 2)
		(c, ans3) = combine(a, n // 2, b, n - n // 2)
		return (c, ans1 + ans2 + ans3)

def combine(l1, n, l2, m):
	i = 0
	j = 0
	ans = []
	inversions = 0
	while i < n and j < m:
		if l1[i] <= l2[j]:
			ans.append(l1[i])
			i += 1
		else:
			ans.append(l2[j])
			inversions += n - i
			j += 1
	if i == n:
		for k in range(j, m):
			ans.append(l2[k])
	elif j == m:
		for k in range(i, n):
			ans.append(l1[k])
	return (ans, inversions)
n = int(input())
start = input()
s = start[::-1]
loc = {}
for i in range(n):
	if s[i] in loc:
		loc[s[i]].append(i)
	else:
		loc[s[i]] = [i]
new = {}
for i in loc:
	new[i] = loc[i][::-1]
arr = []
for i in range(n):
	arr.append(new[start[i]].pop())
print(mergesort(arr, len(arr))[1])


import sys, io, os
BUFSIZE = 8192

class FastIO(io.IOBase):
	newlines = 0

	def __init__(self, file):
		self._fd = file.fileno()
		self.buffer = io.BytesIO()
		self.writable = 'x' in file.mode or 'r' not in file.mode
		self.write = self.buffer.write if self.writable else None

	def read(self):
		while True:
			b = os.read(self._fd, max(os.fstat(self._fd).st_size, BUFSIZE))
			if not b:
				break
			ptr = self.buffer.tell()
			(self.buffer.seek(0, 2), self.buffer.write(b), self.buffer.seek(ptr))
		self.newlines = 0
		return self.buffer.read()

	def readline(self):
		while self.newlines == 0:
			b = os.read(self._fd, max(os.fstat(self._fd).st_size, BUFSIZE))
			self.newlines = b.count(b'\n') + (not b)
			ptr = self.buffer.tell()
			(self.buffer.seek(0, 2), self.buffer.write(b), self.buffer.seek(ptr))
		self.newlines -= 1
		return self.buffer.readline()

	def flush(self):
		if self.writable:
			os.write(self._fd, self.buffer.getvalue())
			(self.buffer.truncate(0), self.buffer.seek(0))

class IOWrapper(io.IOBase):

	def __init__(self, file):
		self.buffer = FastIO(file)
		self.flush = self.buffer.flush
		self.writable = self.buffer.writable
		self.write = lambda s: self.buffer.write(s.encode('ascii'))
		self.read = lambda : self.buffer.read().decode('ascii')
		self.readline = lambda : self.buffer.readline().decode('ascii')

def print(*args, **kwargs):
	(sep, file) = (kwargs.pop('sep', ' '), kwargs.pop('file', sys.stdout))
	at_start = True
	for x in args:
		if not at_start:
			file.write(sep)
		file.write(str(x))
		at_start = False
	file.write(kwargs.pop('end', '\n'))
	if kwargs.pop('flush', False):
		file.flush()
(sys.stdin, sys.stdout) = (IOWrapper(sys.stdin), IOWrapper(sys.stdout))
input = lambda : sys.stdin.readline().rstrip('\r\n')

class Bit:

	def __init__(self, n):
		self.size = n
		self.tree = [0] * (n + 1)

	def __iter__(self):
		psum = 0
		for i in range(self.size):
			csum = self.sum(i + 1)
			yield (csum - psum)
			psum = csum
		raise StopIteration()

	def __str__(self):
		return str(list(self))

	def sum(self, i):
		if not 0 <= i <= self.size:
			raise ValueError('error!')
		s = 0
		while i > 0:
			s += self.tree[i]
			i -= i & -i
		return s

	def add(self, i, x):
		if not 0 <= i < self.size:
			raise ValueError('error!')
		i += 1
		while i <= self.size:
			self.tree[i] += x
			i += i & -i
N = int(input())
S = [ord(s) - 97 for s in input()]
S_rev = list(reversed(S))

def solve(S, S_rev):
	bit = Bit(N)
	Next = [[] for _ in range(26)]
	for (i, sr) in enumerate(S_rev):
		Next[sr].append(i)
	Next = [iter(nex) for nex in Next]
	cnt_all = 0
	ans = 0
	for s in S:
		idx = next(Next[s])
		ans += cnt_all - bit.sum(idx + 1)
		bit.add(idx, 1)
		cnt_all += 1
	return ans
ans = solve(S, S_rev)
print(ans)


n = int(input())
s = input().strip()
character_indexes = [[] for indx in range(26)]
for indx in range(n):
	char_to_append = ord(s[indx]) - 97
	character_indexes[char_to_append].append(indx)
arr = [0 for i in range(n + 2)]
result = 0
freqs = [0 for i in range(26)]
for i in range(n - 1, -1, -1):
	char_to_append = ord(s[i]) - 97
	tmp = character_indexes[char_to_append][freqs[char_to_append]]
	res = 0
	first_tmp = tmp + 1
	while first_tmp != 0:
		res += arr[first_tmp]
		first_tmp -= first_tmp & -first_tmp
	result += tmp - res
	freqs[char_to_append] += 1
	second_tmp = tmp + 1
	while second_tmp <= n:
		arr[second_tmp] += 1
		second_tmp += second_tmp & -second_tmp
print(result)


from __future__ import division, print_function
from fractions import Fraction
import sys
import os
from io import BytesIO, IOBase
from heapq import *
from math import gcd, factorial, floor, ceil
from copy import deepcopy
from collections import deque
from bisect import bisect_left as bl
from bisect import bisect_right as br
from bisect import bisect
BUFSIZE = 8192

class FastIO(IOBase):
	newlines = 0

	def __init__(self, file):
		self._fd = file.fileno()
		self.buffer = BytesIO()
		self.writable = 'x' in file.mode or 'r' not in file.mode
		self.write = self.buffer.write if self.writable else None

	def read(self):
		while True:
			b = os.read(self._fd, max(os.fstat(self._fd).st_size, BUFSIZE))
			if not b:
				break
			ptr = self.buffer.tell()
			(self.buffer.seek(0, 2), self.buffer.write(b), self.buffer.seek(ptr))
		self.newlines = 0
		return self.buffer.read()

	def readline(self):
		while self.newlines == 0:
			b = os.read(self._fd, max(os.fstat(self._fd).st_size, BUFSIZE))
			self.newlines = b.count(b'\n') + (not b)
			ptr = self.buffer.tell()
			(self.buffer.seek(0, 2), self.buffer.write(b), self.buffer.seek(ptr))
		self.newlines -= 1
		return self.buffer.readline()

	def flush(self):
		if self.writable:
			os.write(self._fd, self.buffer.getvalue())
			(self.buffer.truncate(0), self.buffer.seek(0))

class IOWrapper(IOBase):

	def __init__(self, file):
		self.buffer = FastIO(file)
		self.flush = self.buffer.flush
		self.writable = self.buffer.writable
		self.write = lambda s: self.buffer.write(s.encode('ascii'))
		self.read = lambda : self.buffer.read().decode('ascii')
		self.readline = lambda : self.buffer.readline().decode('ascii')

def print(*args, **kwargs):
	(sep, file) = (kwargs.pop('sep', ' '), kwargs.pop('file', sys.stdout))
	at_start = True
	for x in args:
		if not at_start:
			file.write(sep)
		file.write(str(x))
		at_start = False
	file.write(kwargs.pop('end', '\n'))
	if kwargs.pop('flush', False):
		file.flush()
if sys.version_info[0] < 3:
	(sys.stdin, sys.stdout) = (FastIO(sys.stdin), FastIO(sys.stdout))
else:
	(sys.stdin, sys.stdout) = (IOWrapper(sys.stdin), IOWrapper(sys.stdout))
from types import GeneratorType

def iterative(f, stack=[]):

	def wrapped_func(*args, **kwargs):
		if stack:
			return f(*args, **kwargs)
		to = f(*args, **kwargs)
		while True:
			if type(to) is GeneratorType:
				stack.append(to)
				to = next(to)
				continue
			stack.pop()
			if not stack:
				break
			to = stack[-1].send(to)
		return to
	return wrapped_func
mod = 10 ** 9 + 7

def inp():
	return sys.stdin.readline().rstrip('\r\n')

def out(var):
	sys.stdout.write(str(var))

def lis():
	return list(map(int, inp().split()))

def stringlis():
	return list(map(str, inp().split()))

def sep():
	return map(int, inp().split())

def strsep():
	return map(str, inp().split())

def zerolist(n):
	return [0] * n

def nextline():
	out('\n')

def testcase(t):
	for pp in range(t):
		solve(pp)

def printlist(a):
	for p in range(0, len(a)):
		out(str(a[p]) + ' ')

def google(p):
	print('Case #' + str(p) + ': ', end='')

def lcm(a, b):
	return a * b // gcd(a, b)

def power(x, y, p):
	res = 1
	x = x % p
	if x == 0:
		return 0
	while y > 0:
		if y & 1 == 1:
			res = res * x % p
		y = y >> 1
		x = x * x % p
	return res

def ncr(n, r):
	return factorial(n) // (factorial(r) * factorial(max(n - r, 1)))

def isPrime(n):
	if n <= 1:
		return False
	if n <= 3:
		return True
	if n % 2 == 0 or n % 3 == 0:
		return False
	i = 5
	while i * i <= n:
		if n % i == 0 or n % (i + 2) == 0:
			return False
		i = i + 6
	return True

class FenwickTree:

	def __init__(self, x):
		self.bit = x
		for i in range(len(x)):
			j = i | i + 1
			if j < len(x):
				x[j] += x[i]

	def update(self, idx, x):
		while idx < len(self.bit):
			self.bit[idx] += x
			idx |= idx + 1

	def query(self, end):
		x = 0
		while end:
			x += self.bit[end - 1]
			end &= end - 1
		return x

	def findkth(self, k):
		idx = -1
		for d in reversed(range(len(self.bit).bit_length())):
			right_idx = idx + (1 << d)
			if right_idx < len(self.bit) and k >= self.bit[right_idx]:
				idx = right_idx
				k -= self.bit[idx]
		return idx + 1

def solve(case):
	n = int(inp())
	a = list(inp())
	a = a[::-1]
	newpos = {}
	for i in range(n):
		if a[i] in newpos:
			newpos[a[i]].append(i)
		else:
			newpos[a[i]] = deque([i])
	a = a[::-1]
	arr = [0] * n
	for i in range(n):
		arr[i] = newpos[a[i]].popleft() + 1
	arr = arr[::-1]
	BIT = FenwickTree([0] * 2000010)
	ans = 0
	for i in range(n):
		ans += BIT.query(arr[i])
		BIT.update(arr[i], 1)
		new = []
	print(ans)
testcase(1)


import sys, bisect, string, math, time, functools, random, fractions
from heapq import heappush, heappop, heapify
from collections import deque, defaultdict, Counter
from itertools import permutations, combinations, groupby
rep = range
R = range

def Golf():
	(n, *t) = map(int, open(0).read().split())

def I():
	return int(input())

def S_():
	return input()

def IS():
	return input().split()

def LS():
	return [i for i in input().split()]

def MI():
	return map(int, input().split())

def LI():
	return [int(i) for i in input().split()]

def LI_():
	return [int(i) - 1 for i in input().split()]

def NI(n):
	return [int(input()) for i in range(n)]

def NI_(n):
	return [int(input()) - 1 for i in range(n)]

def NLI(n):
	return [[int(i) for i in input().split()] for i in range(n)]

def NLI_(n):
	return [[int(i) - 1 for i in input().split()] for i in range(n)]

def StoLI():
	return [ord(i) - 97 for i in input()]

def ItoS(n):
	return chr(n + 97)

def LtoS(ls):
	return ''.join([chr(i + 97) for i in ls])

def RA():
	return map(int, open(0).read().split())

def RLI(n=8, a=1, b=10):
	return [random.randint(a, b) for i in range(n)]

def RI(a=1, b=10):
	return random.randint(a, b)

def INP():
	N = 10
	A = 10
	n = random.randint(1, N)
	a = [random.randint(1, A) for i in range(n)]
	return (n, a)

def Rtest(T):
	(case, err) = (0, 0)
	for i in range(T):
		inp = INP()
		a1 = naive(*inp)
		a2 = solve(*inp)
		if a1 != a2:
			print((a1, a2), inp)
			err += 1
		case += 1
	print('Tested', case, 'case with', err, 'errors')

def GI(V, E, ls=None, Directed=False, index=1):
	org_inp = []
	g = [[] for i in range(V)]
	FromStdin = True if ls == None else False
	for i in range(E):
		if FromStdin:
			inp = LI()
			org_inp.append(inp)
		else:
			inp = ls[i]
		if len(inp) == 2:
			(a, b) = inp
			c = 1
		else:
			(a, b, c) = inp
		if index == 1:
			a -= 1
			b -= 1
		aa = (a, c)
		bb = (b, c)
		g[a].append(bb)
		if not Directed:
			g[b].append(aa)
	return (g, org_inp)

def GGI(h, w, search=None, replacement_of_found='.', mp_def={'#': 1, '.': 0}, boundary=1):
	mp = [boundary] * (w + 2)
	found = {}
	for i in R(h):
		s = input()
		for char in search:
			if char in s:
				found[char] = (i + 1) * (w + 2) + s.index(char) + 1
				mp_def[char] = mp_def[replacement_of_found]
		mp += [boundary] + [mp_def[j] for j in s] + [boundary]
	mp += [boundary] * (w + 2)
	return (h + 2, w + 2, mp, found)

def TI(n):
	return GI(n, n - 1)

def accum(ls):
	rt = [0]
	for i in ls:
		rt += [rt[-1] + i]
	return rt

def bit_combination(n, base=2):
	rt = []
	for tb in R(base ** n):
		s = [tb // base ** bt % base for bt in R(n)]
		rt += [s]
	return rt

def gcd(x, y):
	if y == 0:
		return x
	if x % y == 0:
		return y
	while x % y != 0:
		(x, y) = (y, x % y)
	return y

def YN(x):
	print(['NO', 'YES'][x])

def Yn(x):
	print(['No', 'Yes'][x])

def show(*inp, end='\n'):
	if show_flg:
		print(*inp, end=end)
mo = 10 ** 9 + 7
inf = float('inf')
FourNb = [(-1, 0), (1, 0), (0, 1), (0, -1)]
EightNb = [(-1, 0), (1, 0), (0, 1), (0, -1), (1, 1), (-1, -1), (1, -1), (-1, 1)]
compas = dict(zip('WENS', FourNb))
cursol = dict(zip('LRUD', FourNb))
l_alp = string.ascii_lowercase
read = sys.stdin.buffer.read
readline = sys.stdin.buffer.readline
input = lambda : sys.stdin.readline().rstrip()

class UnionFind:

	def __init__(self, n):
		self.table = [-1] * n

	def _root(self, x):
		if self.table[x] < 0:
			return x
		else:
			self.table[x] = self._root(self.table[x])
			return self.table[x]

	def find(self, x, y):
		return self._root(x) == self._root(y)

	def union(self, x, y):
		r1 = self._root(x)
		r2 = self._root(y)
		if r1 == r2:
			return
		d1 = self.table[r1]
		d2 = self.table[r2]
		if d1 <= d2:
			self.table[r2] = r1
			if d1 == d2:
				self.table[r1] -= 1
		else:
			self.table[r1] = r2

	def __str__(self):
		rt = [i if j < 0 else j for (i, j) in enumerate(self.table)]
		return str(rt)
show_flg = False
show_flg = True
ans = 0
n = I()
s = input()
t = s[::-1]
p = defaultdict(list)
for i in range(n):
	p[t[i]].append(i)
m = [0] * n
d = dict(zip(l_alp, range(26)))
k = [0] * 26
for i in range(n):
	m[p[s[i]][k[d[s[i]]]]] = i
	k[d[s[i]]] += 1

class Bit:

	def __init__(self, n):
		self.size = n
		self.m = len(bin(self.size)) - 2
		self.arr = [0] * (2 ** self.m + 1)

	def __str__(self):
		return str(self.arr)

	def add(self, i, x):
		k = 0
		while i <= self.size:
			k += 1
			self.arr[i] += x
			i += i & -i
		return

	def sum(self, i):
		rt = 0
		while i > 0:
			rt += self.arr[i]
			i -= i & -i
		return rt

	def l_bound(self, w):
		if w <= 0:
			return 0
		x = 0
		k = 2 ** self.m
		while k > 0:
			if x + k < self.size and self.arr[x + k] < w:
				w -= self.arr[x + k]
				x += k
			k //= 2
		return x + 1

	def u_bound(self, w):
		if w <= 0:
			return 0
		x = 0
		k = 2 ** self.m
		while k > 0:
			if x + k < self.size and self.arr[x + k] <= w:
				w -= self.arr[x + k]
				x += k
			k //= 2
		return x + 1

class Bit0(Bit):

	def add(self, j, x):
		super().add(j + 1, x)

	def l_bound(self, w):
		return max(super().l_bound(w) - 1, 0)

	def u_bound(self, w):
		return max(super().u_bound(w) - 1, 0)

class Multiset(Bit0):

	def __init__(self, max_v):
		super().__init__(max_v)

	def insert(self, x):
		super().add(x, 1)

	def find(self, x):
		return super().l_bound(super().sum(x))

	def __str__(self):
		return str(self.arr)

class Comb:

	def __init__(self, n, mo=10 ** 9 + 7):
		self.fac = [0] * (n + 1)
		self.inv = [1] * (n + 1)
		self.fac[0] = 1
		self.fact(n)
		for i in range(1, n + 1):
			self.fac[i] = i * self.fac[i - 1] % mo
			self.inv[n] *= i
			self.inv[n] %= mo
		self.inv[n] = pow(self.inv[n], mo - 2, mo)
		for i in range(1, n):
			self.inv[n - i] = self.inv[n - i + 1] * (n - i + 1) % mo
		return

	def fact(self, n):
		return self.fac[n]

	def invf(self, n):
		return self.inv[n]

	def comb(self, x, y):
		if y < 0 or y > x:
			return 0
		return self.fac[x] * self.inv[x - y] * self.inv[y] % mo
ans = 0
bt = Bit0(n + 1)
for i in m:
	c = bt.sum(n + 1) - bt.sum(i)
	ans += c
	bt.add(i, 1)
print(ans)


from sys import stdin, stdout
import math, sys, heapq
from itertools import permutations, combinations
from collections import defaultdict, deque, OrderedDict
from os import path
import random
import bisect as bi

def yes():
	print('YES')

def no():
	print('NO')
if path.exists('input.txt'):
	sys.stdin = open('input.txt', 'r')
	sys.stdout = open('output.txt', 'w')

	def I():
		return int(input())

	def In():
		return map(int, input().split())
else:

	def I():
		return int(stdin.readline())

	def In():
		return map(int, stdin.readline().split())

def dict(a):
	d = {}
	for x in a:
		if d.get(x, -1) != -1:
			d[x] += 1
		else:
			d[x] = 1
	return d

def find_gt(a, x):
	i = bi.bisect_left(a, x)
	if i != len(a):
		return i
	else:
		return -1

def getSum(BITree, index):
	sum = 0
	while index > 0:
		sum += BITree[index]
		index -= index & -index
	return sum

def updateBIT(BITree, n, index, val):
	while index <= n:
		BITree[index] += val
		index += index & -index

def getInvCount(arr, n):
	invcount = 0
	maxElement = max(arr)
	BIT = [0] * (maxElement + 1)
	for i in range(1, maxElement + 1):
		BIT[i] = 0
	for i in range(n - 1, -1, -1):
		invcount += getSum(BIT, arr[i] - 1)
		updateBIT(BIT, maxElement, arr[i], 1)
	return invcount

def main():
	try:
		n = I()
		d = defaultdict(deque)
		S = input()
		for i in range(n):
			d[S[i]].append(i)
		reversal = []
		for i in range(n - 1, -1, -1):
			reversal.append(d[S[i]].popleft() + 1)
		ans = getInvCount(reversal, n)
		print(ans)
	except:
		pass
M = 998244353
P = 1000000007
for _ in range(1):
	main()


import sys, os
from math import sqrt, gcd, ceil, log, floor
from bisect import bisect, bisect_left
from collections import defaultdict, Counter, deque
from heapq import heapify, heappush, heappop
input = sys.stdin.readline
read = lambda : list(map(int, input().strip().split()))
from time import time
MOD = 998244353
BIT = [0] * (2 * 10 ** 5 + 1)

def update(ind, val, n):
	while ind <= n:
		BIT[ind] += val
		ind += ind & -ind

def pref_sum(ind):
	s = 0
	while ind > 0:
		s += BIT[ind]
		ind -= ind & -ind
	return s

def drive():
	(n, k) = read()
	arr = read()
	print(arr)
	for i in range(1, n + 1):
		update(i, arr[i - 1], n)
	print(BIT[:n + 1])
	for i in range(k):
		(i, j) = read()
		if i:
			print(pref_sum(j) - pref_sum(i - 1))
		else:
			update(i, arr[j], n)
			print(BIT)

def main():
	n = int(input())
	s = input()
	POS = [deque() for i in range(26)]
	for i in range(n):
		POS[ord(s[i]) - 97].append(i)
	arr = []
	for i in range(n - 1, -1, -1):
		arr.append(POS[ord(s[i]) - 97].popleft() + 1)
	ans = 0
	for i in arr:
		ans += pref_sum(n) - pref_sum(i)
		update(i, 1, n)
	print(ans)
main()


def build(v, l, r):
	nonlocal tree
	if r - l == 1:
		tree[v] = u[l]
	else:
		m = (l + r) // 2
		build(2 * v + 1, l, m)
		build(2 * v + 2, m, r)
		tree[v] = tree[2 * v + 1] + tree[2 * v + 2]

def rsq(v, l, r, a, b):
	nonlocal tree
	if l >= b or a >= r:
		return 0
	if l >= a and r <= b:
		return tree[v]
	m = (l + r) // 2
	return rsq(2 * v + 1, l, m, a, b) + rsq(2 * v + 2, m, r, a, b)

def update(v, l, r, i, x):
	nonlocal tree
	if i < l or i >= r:
		return
	if r - l == 1:
		tree[v] = x
	else:
		m = (l + r) // 2
		update(2 * v + 1, l, m, i, x)
		update(2 * v + 2, m, r, i, x)
		tree[v] = tree[2 * v + 1] + tree[2 * v + 2]
n = int(input())
a = list(input())
sz = 1
while sz < n:
	sz *= 2
tree = [0] * (2 * sz - 1)
u = [0] * n
while len(u) < sz:
	u.append(0)
build(0, 0, sz)
ss = []
for i in range(26):
	ss.append([])
for i in range(n):
	a[i] = ord(a[i]) - ord('a')
	ss[a[i]].append(i)
a.reverse()
ans = 0
for i in range(n - 1, -1, -1):
	(L, R) = (ss[a[i]][-1], i)
	ans += R - L + rsq(0, 0, sz, 0, L)
	update(0, 0, sz, L, 1)
	ss[a[i]].pop()
print(ans)


N = int(input())
S = input()
T = S[::-1]
from collections import defaultdict
dic = defaultdict(lambda : [])
for (i, t) in enumerate(T):
	dic[t].append(i)
for k in dic.keys():
	dic[k].reverse()
arr = []
for c in S:
	arr.append(dic[c].pop())

def inversion(inds):
	bit = [0] * (N + 1)

	def bit_add(x, w):
		while x <= N:
			bit[x] += w
			x += x & -x

	def bit_sum(x):
		ret = 0
		while x > 0:
			ret += bit[x]
			x -= x & -x
		return ret
	inv = 0
	for ind in reversed(inds):
		inv += bit_sum(ind + 1)
		bit_add(ind + 1, 1)
	return inv
print(inversion(arr))


import sys, os
from io import BytesIO, IOBase
from functools import lru_cache
mod = 10 ** 9 + 7
Mod = 998244353
INF = float('inf')
BUFSIZE = 8192

class FastIO(IOBase):
	newlines = 0

	def __init__(self, file):
		self._fd = file.fileno()
		self.buffer = BytesIO()
		self.writable = 'x' in file.mode or 'r' not in file.mode
		self.write = self.buffer.write if self.writable else None

	def read(self):
		while True:
			b = os.read(self._fd, max(os.fstat(self._fd).st_size, BUFSIZE))
			if not b:
				break
			ptr = self.buffer.tell()
			(self.buffer.seek(0, 2), self.buffer.write(b), self.buffer.seek(ptr))
		self.newlines = 0
		return self.buffer.read()

	def readline(self):
		while self.newlines == 0:
			b = os.read(self._fd, max(os.fstat(self._fd).st_size, BUFSIZE))
			self.newlines = b.count(b'\n') + (not b)
			ptr = self.buffer.tell()
			(self.buffer.seek(0, 2), self.buffer.write(b), self.buffer.seek(ptr))
		self.newlines -= 1
		return self.buffer.readline()

	def flush(self):
		if self.writable:
			os.write(self._fd, self.buffer.getvalue())
			(self.buffer.truncate(0), self.buffer.seek(0))

class IOWrapper(IOBase):

	def __init__(self, file):
		self.buffer = FastIO(file)
		self.flush = self.buffer.flush
		self.writable = self.buffer.writable
		self.write = lambda s: self.buffer.write(s.encode('ascii'))
		self.read = lambda : self.buffer.read().decode('ascii')
		self.readline = lambda : self.buffer.readline().decode('ascii')
(sys.stdin, sys.stdout) = (IOWrapper(sys.stdin), IOWrapper(sys.stdout))
input = lambda : sys.stdin.readline().rstrip('\r\n')
inp = lambda : list(map(int, sys.stdin.readline().rstrip('\r\n').split()))
from collections import defaultdict as dd
tc = 1

def mergeSort(left, right, arr, temp):
	inv_cnt = 0
	if left < right:
		mid = (left + right) // 2
		inv1 = mergeSort(left, mid, arr, temp)
		inv2 = mergeSort(mid + 1, right, arr, temp)
		inv3 = merge(left, right, mid, arr, temp)
		inv_cnt = inv1 + inv3 + inv2
	return inv_cnt

def merge(left, right, mid, arr, temp):
	i = left
	j = mid + 1
	k = left
	inv = 0
	while i <= mid and j <= right:
		if arr[i] <= arr[j]:
			temp[k] = arr[i]
			i += 1
		else:
			temp[k] = arr[j]
			inv += mid + 1 - i
			j += 1
		k += 1
	while i <= mid:
		temp[k] = arr[i]
		i += 1
		k += 1
	while j <= right:
		temp[k] = arr[j]
		j += 1
		k += 1
	for k in range(left, right + 1):
		arr[k] = temp[k]
	return inv
for test in range(1, tc + 1):
	n = int(input())
	a = list(input())
	b = a[::-1]
	d = dd(list)
	for i in range(n):
		d[b[i]].append(i)
	for i in d.keys():
		d[i].reverse()
	arr = []
	for i in a:
		arr.append(d[i].pop())
	temp = arr.copy()
	ans = mergeSort(0, n - 1, arr, temp)
	print(ans)


from heapq import heappop
import os.path
from math import gcd, floor, ceil
from collections import *
import sys
from heapq import *
mod = 1000000007
INF = float('inf')

def st():
	return list(sys.stdin.readline().strip())

def li():
	return list(map(int, sys.stdin.readline().split()))

def mp():
	return map(int, sys.stdin.readline().split())

def inp():
	return int(sys.stdin.readline())

def pr(n):
	return sys.stdout.write(str(n) + '\n')

def prl(n):
	return sys.stdout.write(str(n) + ' ')
if os.path.exists('input.txt'):
	sys.stdin = open('input.txt', 'r')
	sys.stdout = open('output.txt', 'w')

def solve():

	def update(ind, val):
		while ind <= n:
			BIT[ind] += val
			ind += ind & -ind

	def query(ind):
		su = 0
		while ind > 0:
			su += BIT[ind]
			ind -= ind & -ind
		return su
	n = inp()
	s = ['&'] + st()
	d = defaultdict(list)
	n += 1
	for i in range(1, n):
		d[s[i]].append(i)
	BIT = [0] * (n + 2)
	ans = 0
	p = [0] * (n + 1)
	for i in range(n - 1, 0, -1):
		last = d[s[n - i]].pop()
		p[i] = last
	for i in range(1, n):
		c = query(n) - query(p[i])
		ans += c
		update(p[i], 1)
	pr(ans)
for _ in range(1):
	solve()


from collections import defaultdict, Counter

class FenwickTree:

	def __init__(self, n):
		self.tree = [0] * (n + 1)

	def _get(self, x):
		res = 0
		while x >= 1:
			res += self.tree[x]
			x -= x & -x
		return res

	def get(self, l, r):
		return self._get(r) - self._get(l - 1)

	def add(self, x, d):
		while x < len(self.tree):
			self.tree[x] += d
			x += x & -x

def inversions(a):
	n = len(a)
	res = 0
	count = FenwickTree(n)
	for e in a:
		res += count.get(e + 1, n)
		count.add(e, 1)
	return res
n = int(input())
s = input()
d = defaultdict(list)
for (i, e) in enumerate(s[::-1]):
	d[e].append(i + 1)
c = Counter()
a = []
for e in s:
	a.append(d[e][c[e]])
	c[e] += 1
print(inversions(a))


from __future__ import division, print_function
import os
import sys, math
from io import BytesIO, IOBase
from itertools import permutations, combinations
from collections import defaultdict, deque, OrderedDict
from os import path
import random
import bisect as bi

def yes():
	print('YES')

def no():
	print('NO')

def I():
	return int(input())

def In():
	return map(int, input().split())

def getSum(BITree, index):
	sum = 0
	while index > 0:
		sum += BITree[index]
		index -= index & -index
	return sum

def updateBIT(BITree, n, index, val):
	while index <= n:
		BITree[index] += val
		index += index & -index

def getInvCount(arr, n):
	invcount = 0
	maxElement = max(arr)
	BIT = [0] * (maxElement + 1)
	for i in range(1, maxElement + 1):
		BIT[i] = 0
	for i in range(n - 1, -1, -1):
		invcount += getSum(BIT, arr[i] - 1)
		updateBIT(BIT, maxElement, arr[i], 1)
	return invcount

def main():
	try:
		n = I()
		d = defaultdict(deque)
		S = input()
		for i in range(n):
			d[S[i]].append(i)
		reversal = []
		for i in range(n - 1, -1, -1):
			reversal.append(d[S[i]].popleft() + 1)
		ans = getInvCount(reversal, n)
		print(ans)
	except:
		pass
M = 998244353
P = 1000000007
BUFSIZE = 8192

class FastIO(IOBase):
	newlines = 0

	def __init__(self, file):
		self._fd = file.fileno()
		self.buffer = BytesIO()
		self.writable = 'x' in file.mode or 'r' not in file.mode
		self.write = self.buffer.write if self.writable else None

	def read(self):
		while True:
			b = os.read(self._fd, max(os.fstat(self._fd).st_size, BUFSIZE))
			if not b:
				break
			ptr = self.buffer.tell()
			(self.buffer.seek(0, 2), self.buffer.write(b), self.buffer.seek(ptr))
		self.newlines = 0
		return self.buffer.read()

	def readline(self):
		while self.newlines == 0:
			b = os.read(self._fd, max(os.fstat(self._fd).st_size, BUFSIZE))
			self.newlines = b.count(b'\n') + (not b)
			ptr = self.buffer.tell()
			(self.buffer.seek(0, 2), self.buffer.write(b), self.buffer.seek(ptr))
		self.newlines -= 1
		return self.buffer.readline()

	def flush(self):
		if self.writable:
			os.write(self._fd, self.buffer.getvalue())
			(self.buffer.truncate(0), self.buffer.seek(0))

class IOWrapper(IOBase):

	def __init__(self, file):
		self.buffer = FastIO(file)
		self.flush = self.buffer.flush
		self.writable = self.buffer.writable
		self.write = lambda s: self.buffer.write(s.encode('ascii'))
		self.read = lambda : self.buffer.read().decode('ascii')
		self.readline = lambda : self.buffer.readline().decode('ascii')

def print(*args, **kwargs):
	(sep, file) = (kwargs.pop('sep', ' '), kwargs.pop('file', sys.stdout))
	at_start = True
	for x in args:
		if not at_start:
			file.write(sep)
		file.write(str(x))
		at_start = False
	file.write(kwargs.pop('end', '\n'))
	if kwargs.pop('flush', False):
		file.flush()
if sys.version_info[0] < 3:
	(sys.stdin, sys.stdout) = (FastIO(sys.stdin), FastIO(sys.stdout))
else:
	(sys.stdin, sys.stdout) = (IOWrapper(sys.stdin), IOWrapper(sys.stdout))
input = lambda : sys.stdin.readline().rstrip('\r\n')
for _ in range(1):
	main()


from collections import defaultdict, deque
n = int(input())
s = input()

def mergesort(arr, n):
	temp_arr = [0] * n
	return _mergesort(arr, temp_arr, 0, n - 1)

def _mergesort(arr, temp, l, r):
	ans = 0
	if l < r:
		mid = (l + r) // 2
		ans += _mergesort(arr, temp, l, mid)
		ans += _mergesort(arr, temp, mid + 1, r)
		ans += merge(arr, temp, l, mid, r)
	return ans

def merge(arr, temp, l, mid, r):
	count = 0
	i = l
	j = mid + 1
	nxt = l
	while i <= mid and j <= r:
		if arr[i] <= arr[j]:
			temp[nxt] = arr[i]
			nxt += 1
			i += 1
		else:
			count += mid - i + 1
			temp[nxt] = arr[j]
			nxt += 1
			j += 1
	while i <= mid:
		temp[nxt] = arr[i]
		nxt += 1
		i += 1
	while j <= r:
		temp[nxt] = arr[j]
		nxt += 1
		j += 1
	arr[l:r + 1] = temp[l:r + 1][:]
	return count
dic = defaultdict(lambda : deque())
rev = s[::-1]
for (i, char) in enumerate(rev):
	dic[char].append(i + 1)
arr = []
for i in s:
	arr.append(dic[i].popleft())
n = len(arr)
print(mergesort(arr, n))


def mergeSort(arr, n):
	temp_arr = [0] * n
	return _mergeSort(arr, temp_arr, 0, n - 1)

def _mergeSort(arr, temp_arr, left, right):
	inv_count = 0
	if left < right:
		mid = (left + right) // 2
		inv_count += _mergeSort(arr, temp_arr, left, mid)
		inv_count += _mergeSort(arr, temp_arr, mid + 1, right)
		inv_count += merge(arr, temp_arr, left, mid, right)
	return inv_count

def merge(arr, temp_arr, left, mid, right):
	i = left
	j = mid + 1
	k = left
	inv_count = 0
	while i <= mid and j <= right:
		if arr[i] <= arr[j]:
			temp_arr[k] = arr[i]
			k += 1
			i += 1
		else:
			temp_arr[k] = arr[j]
			inv_count += mid - i + 1
			k += 1
			j += 1
	while i <= mid:
		temp_arr[k] = arr[i]
		k += 1
		i += 1
	while j <= right:
		temp_arr[k] = arr[j]
		k += 1
		j += 1
	for loop_var in range(left, right + 1):
		arr[loop_var] = temp_arr[loop_var]
	return inv_count
n = int(input())
string = input()
occurences = [list() for _ in range(26)]
for i in range(n):
	pos = ord(string[i]) - ord('a')
	occurences[pos].append(i)
reversed = list()
for i in range(n - 1, -1, -1):
	reversed.append(string[i])
inversion = [0] * n
for i in range(n - 1, -1, -1):
	pos = ord(reversed[i]) - ord('a')
	inversion[i] = occurences[pos].pop()
print(mergeSort(inversion, n))


import sys
sys.setrecursionlimit(10 ** 5)
int1 = lambda x: int(x) - 1
p2D = lambda x: print(*x, sep='\n')

def II():
	return int(sys.stdin.buffer.readline())

def MI():
	return map(int, sys.stdin.buffer.readline().split())

def LI():
	return list(map(int, sys.stdin.buffer.readline().split()))

def LLI(rows_number):
	return [LI() for _ in range(rows_number)]

def BI():
	return sys.stdin.buffer.readline().rstrip()

def SI():
	return sys.stdin.buffer.readline().rstrip().decode()

class BitSum:

	def __init__(self, n):
		self.n = n + 1
		self.table = [0] * self.n

	def add(self, i, x):
		i += 1
		while i < self.n:
			self.table[i] += x
			i += i & -i

	def sum(self, i):
		i += 1
		res = 0
		while i > 0:
			res += self.table[i]
			i -= i & -i
		return res
n = II()
s = BI()
rs = s[::-1]
pos = [[] for _ in range(26)]
for i in range(n - 1, -1, -1):
	c = rs[i] - 97
	pos[c].append(i)
aa = []
for c in s:
	c -= 97
	i = pos[c].pop()
	aa.append(i)
bit = BitSum(n)
ans = 0
for (i, a) in enumerate(aa):
	ans += i - bit.sum(a)
	bit.add(a, 1)
print(ans)


import math, sys, os
from collections import defaultdict, deque, OrderedDict, Counter
import bisect as bi
from io import BytesIO, IOBase
mod = 10 ** 9 + 7
BUFSIZE = 8192

class FastIO(IOBase):
	newlines = 0

	def __init__(self, file):
		self._fd = file.fileno()
		self.buffer = BytesIO()
		self.writable = 'x' in file.mode or 'r' not in file.mode
		self.write = self.buffer.write if self.writable else None

	def read(self):
		while True:
			b = os.read(self._fd, max(os.fstat(self._fd).st_size, BUFSIZE))
			if not b:
				break
			ptr = self.buffer.tell()
			(self.buffer.seek(0, 2), self.buffer.write(b), self.buffer.seek(ptr))
		self.newlines = 0
		return self.buffer.read()

	def readline(self):
		while self.newlines == 0:
			b = os.read(self._fd, max(os.fstat(self._fd).st_size, BUFSIZE))
			self.newlines = b.count(b'\n') + (not b)
			ptr = self.buffer.tell()
			(self.buffer.seek(0, 2), self.buffer.write(b), self.buffer.seek(ptr))
		self.newlines -= 1
		return self.buffer.readline()

	def flush(self):
		if self.writable:
			os.write(self._fd, self.buffer.getvalue())
			(self.buffer.truncate(0), self.buffer.seek(0))

class IOWrapper(IOBase):

	def __init__(self, file):
		self.buffer = FastIO(file)
		self.flush = self.buffer.flush
		self.writable = self.buffer.writable
		self.write = lambda s: self.buffer.write(s.encode('ascii'))
		self.read = lambda : self.buffer.read().decode('ascii')
		self.readline = lambda : self.buffer.readline().decode('ascii')
(sys.stdin, sys.stdout) = (IOWrapper(sys.stdin), IOWrapper(sys.stdout))
input = lambda : sys.stdin.readline().rstrip('\r\n')

def minp():
	return map(int, sys.stdin.readline().rstrip().split())

def linp():
	return list(map(int, sys.stdin.readline().rstrip().split()))

def inp():
	return int(input())

def print_list(l):
	print(' '.join(map(str, l)))

def BinarySearch(a, x):
	i = bi.bisect_left(a, x)
	if i != len(a) and a[i] == x:
		return i
	else:
		return -1

def gcd(a, b):
	return math.gcd(a, b)

def is_prime(n):
	if n < 5 or n & 1 == 0 or n % 3 == 0:
		return 2 <= n <= 3
	s = (n - 1 & 1 - n).bit_length() - 1
	d = n >> s
	for a in [2, 325, 9375, 28178, 450775, 9780504, 1795265022]:
		p = pow(a, d, n)
		if p == 1 or p == n - 1 or a % n == 0:
			continue
		for _ in range(s):
			p = p * p % n
			if p == n - 1:
				break
		else:
			return False
	return True

def mulinverse(a):
	return pow(a, mod - 2, mod)

def main():
	n = int(input())
	s = input()
	pos = [[] for _ in range(26)]
	order = [-1] * n
	for (i, c) in enumerate(s):
		pos[ord(c) - 97].append(i)
	for (i, c) in enumerate(s):
		order[i] = pos[ord(c) - 97].pop()
	bit = [0] * n
	ans = 0
	for o in order:
		x = o + 1
		while x:
			ans += bit[x - 1]
			x &= x - 1
		x = o
		while x < n:
			bit[x] += 1
			x |= x + 1
	print(ans)
main()


from heapq import heappush, heappop
n = int(input())
s = input()
r = s[-1::-1]
count = 0
dict = {}
arr = []
for i in range(n):
	if r[i] in dict:
		heappush(dict[r[i]], i)
	else:
		dict[r[i]] = []
		heappush(dict[r[i]], i)
for i in range(n):
	arr.append(heappop(dict[s[i]]))

def mergesort(arr, si, ei, count):
	if si == ei:
		return ([arr[si]], count)
	mid = (si + ei) // 2
	(a, ac) = mergesort(arr, si, mid, count)
	(b, bc) = mergesort(arr, mid + 1, ei, count)
	count = ac + bc
	ans = []
	i = 0
	j = 0
	la = len(a)
	lb = len(b)
	while i < la and j < lb:
		if a[i] < b[j]:
			ans.append(a[i])
			i += 1
		elif a[i] > b[j]:
			count += la - i
			ans.append(b[j])
			j += 1
	while i < la:
		ans.append(a[i])
		i += 1
	while j < lb:
		ans.append(b[j])
		j += 1
	return (ans, count)
print(mergesort(arr, 0, n - 1, count)[1])


n = int(input())
s = input()
rev_s = s[::-1]
mapping = dict()
ct = 1
for i in rev_s:
	if i in mapping:
		mapping[i].append(ct)
	else:
		mapping[i] = [ct]
	ct += 1
output_arr = []
iptr = dict()
for i in s:
	if i not in iptr:
		iptr[i] = -1
	iptr[i] += 1
	output_arr.append(mapping[i][iptr[i]])

def ct_inv(A):
	ans = 0
	for i in range(len(A)):
		for j in range(i + 1, len(A)):
			if A[i] > A[j]:
				ans += 1
	return ans
fenw = [0 for i in range(n + 2)]

def update(x):
	idx = x
	while idx <= n + 1:
		fenw[idx] += 1
		idx += idx & -idx

def query(idx):
	ans = 0
	while idx > 0:
		ans += fenw[idx]
		idx -= idx & -idx
	return ans

def count_inversions(A):
	ans = 0
	for i in A:
		ans += query(n) - query(i)
		update(i)
	return ans
print(count_inversions(output_arr))


import os
import sys
from io import BytesIO, IOBase

class SortedList:

	def __init__(self, iterable=None, _load=200):
		if iterable is None:
			iterable = []
		values = sorted(iterable)
		self._len = _len = len(values)
		self._load = _load
		self._lists = _lists = [values[i:i + _load] for i in range(0, _len, _load)]
		self._list_lens = [len(_list) for _list in _lists]
		self._mins = [_list[0] for _list in _lists]
		self._fen_tree = []
		self._rebuild = True

	def _fen_build(self):
		self._fen_tree[:] = self._list_lens
		_fen_tree = self._fen_tree
		for i in range(len(_fen_tree)):
			if i | i + 1 < len(_fen_tree):
				_fen_tree[i | i + 1] += _fen_tree[i]
		self._rebuild = False

	def _fen_update(self, index, value):
		if not self._rebuild:
			_fen_tree = self._fen_tree
			while index < len(_fen_tree):
				_fen_tree[index] += value
				index |= index + 1

	def _fen_query(self, end):
		if self._rebuild:
			self._fen_build()
		_fen_tree = self._fen_tree
		x = 0
		while end:
			x += _fen_tree[end - 1]
			end &= end - 1
		return x

	def _fen_findkth(self, k):
		_list_lens = self._list_lens
		if k < _list_lens[0]:
			return (0, k)
		if k >= self._len - _list_lens[-1]:
			return (len(_list_lens) - 1, k + _list_lens[-1] - self._len)
		if self._rebuild:
			self._fen_build()
		_fen_tree = self._fen_tree
		idx = -1
		for d in reversed(range(len(_fen_tree).bit_length())):
			right_idx = idx + (1 << d)
			if right_idx < len(_fen_tree) and k >= _fen_tree[right_idx]:
				idx = right_idx
				k -= _fen_tree[idx]
		return (idx + 1, k)

	def _delete(self, pos, idx):
		_lists = self._lists
		_mins = self._mins
		_list_lens = self._list_lens
		self._len -= 1
		self._fen_update(pos, -1)
		del _lists[pos][idx]
		_list_lens[pos] -= 1
		if _list_lens[pos]:
			_mins[pos] = _lists[pos][0]
		else:
			del _lists[pos]
			del _list_lens[pos]
			del _mins[pos]
			self._rebuild = True

	def _loc_left(self, value):
		if not self._len:
			return (0, 0)
		_lists = self._lists
		_mins = self._mins
		(lo, pos) = (-1, len(_lists) - 1)
		while lo + 1 < pos:
			mi = lo + pos >> 1
			if value <= _mins[mi]:
				pos = mi
			else:
				lo = mi
		if pos and value <= _lists[pos - 1][-1]:
			pos -= 1
		_list = _lists[pos]
		(lo, idx) = (-1, len(_list))
		while lo + 1 < idx:
			mi = lo + idx >> 1
			if value <= _list[mi]:
				idx = mi
			else:
				lo = mi
		return (pos, idx)

	def _loc_right(self, value):
		if not self._len:
			return (0, 0)
		_lists = self._lists
		_mins = self._mins
		(pos, hi) = (0, len(_lists))
		while pos + 1 < hi:
			mi = pos + hi >> 1
			if value < _mins[mi]:
				hi = mi
			else:
				pos = mi
		_list = _lists[pos]
		(lo, idx) = (-1, len(_list))
		while lo + 1 < idx:
			mi = lo + idx >> 1
			if value < _list[mi]:
				idx = mi
			else:
				lo = mi
		return (pos, idx)

	def add(self, value):
		_load = self._load
		_lists = self._lists
		_mins = self._mins
		_list_lens = self._list_lens
		self._len += 1
		if _lists:
			(pos, idx) = self._loc_right(value)
			self._fen_update(pos, 1)
			_list = _lists[pos]
			_list.insert(idx, value)
			_list_lens[pos] += 1
			_mins[pos] = _list[0]
			if _load + _load < len(_list):
				_lists.insert(pos + 1, _list[_load:])
				_list_lens.insert(pos + 1, len(_list) - _load)
				_mins.insert(pos + 1, _list[_load])
				_list_lens[pos] = _load
				del _list[_load:]
				self._rebuild = True
		else:
			_lists.append([value])
			_mins.append(value)
			_list_lens.append(1)
			self._rebuild = True

	def discard(self, value):
		_lists = self._lists
		if _lists:
			(pos, idx) = self._loc_right(value)
			if idx and _lists[pos][idx - 1] == value:
				self._delete(pos, idx - 1)

	def remove(self, value):
		_len = self._len
		self.discard(value)
		if _len == self._len:
			raise ValueError('{0!r} not in list'.format(value))

	def pop(self, index=-1):
		(pos, idx) = self._fen_findkth(self._len + index if index < 0 else index)
		value = self._lists[pos][idx]
		self._delete(pos, idx)
		return value

	def bisect_left(self, value):
		(pos, idx) = self._loc_left(value)
		return self._fen_query(pos) + idx

	def bisect_right(self, value):
		(pos, idx) = self._loc_right(value)
		return self._fen_query(pos) + idx

	def count(self, value):
		return self.bisect_right(value) - self.bisect_left(value)

	def __len__(self):
		return self._len

	def __getitem__(self, index):
		(pos, idx) = self._fen_findkth(self._len + index if index < 0 else index)
		return self._lists[pos][idx]

	def __delitem__(self, index):
		(pos, idx) = self._fen_findkth(self._len + index if index < 0 else index)
		self._delete(pos, idx)

	def __contains__(self, value):
		_lists = self._lists
		if _lists:
			(pos, idx) = self._loc_left(value)
			return idx < len(_lists[pos]) and _lists[pos][idx] == value
		return False

	def __iter__(self):
		return (value for _list in self._lists for value in _list)

	def __reversed__(self):
		return (value for _list in reversed(self._lists) for value in reversed(_list))

	def __repr__(self):
		return 'SortedList({0})'.format(list(self))

def main():
	n = int(input())
	s = list(map(lambda x: ord(x) - 97, input().rstrip()))
	(s1, a, p) = (s[::-1], [[] for _ in range(26)], [])
	for i in range(n - 1, -1, -1):
		a[s1[i]].append(i)
	for i in s:
		p.append(a[i].pop())
	(a, ans) = (SortedList([p[-1]]), 0)
	for i in range(n - 2, -1, -1):
		z = a.bisect_left(p[i])
		ans += z
		a.add(p[i])
	print(ans)
BUFSIZE = 8192

class FastIO(IOBase):
	newlines = 0

	def __init__(self, file):
		self._fd = file.fileno()
		self.buffer = BytesIO()
		self.writable = 'x' in file.mode or 'r' not in file.mode
		self.write = self.buffer.write if self.writable else None

	def read(self):
		while True:
			b = os.read(self._fd, max(os.fstat(self._fd).st_size, BUFSIZE))
			if not b:
				break
			ptr = self.buffer.tell()
			(self.buffer.seek(0, 2), self.buffer.write(b), self.buffer.seek(ptr))
		self.newlines = 0
		return self.buffer.read()

	def readline(self):
		while self.newlines == 0:
			b = os.read(self._fd, max(os.fstat(self._fd).st_size, BUFSIZE))
			self.newlines = b.count(b'\n') + (not b)
			ptr = self.buffer.tell()
			(self.buffer.seek(0, 2), self.buffer.write(b), self.buffer.seek(ptr))
		self.newlines -= 1
		return self.buffer.readline()

	def flush(self):
		if self.writable:
			os.write(self._fd, self.buffer.getvalue())
			(self.buffer.truncate(0), self.buffer.seek(0))

class IOWrapper(IOBase):

	def __init__(self, file):
		self.buffer = FastIO(file)
		self.flush = self.buffer.flush
		self.writable = self.buffer.writable
		self.write = lambda s: self.buffer.write(s.encode('ascii'))
		self.read = lambda : self.buffer.read().decode('ascii')
		self.readline = lambda : self.buffer.readline().decode('ascii')
(sys.stdin, sys.stdout) = (IOWrapper(sys.stdin), IOWrapper(sys.stdout))
input = lambda : sys.stdin.readline().rstrip('\r\n')
main()


from collections import deque, defaultdict
n = int(input())
s = input()
dic = defaultdict(lambda : deque())
rev = s[::-1]
for (i, char) in enumerate(rev):
	dic[char].append(i + 1)
arr = []
for i in s:
	arr.append(dic[i].popleft())

class BIT:

	def __init__(self, lis, n):
		self.n = n
		self.array = [0] + lis
		for idx in range(1, n):
			idx2 = idx + (idx & -idx)
			if idx2 < n:
				self.array[idx2] += self.array[idx]

	def prefix_query(self, idx):
		idx += 1
		result = 0
		while idx > 0:
			result += self.array[idx]
			idx -= idx & -idx
		return result

	def range_query(self, from_idx, to_idx):
		return self.prefix_query(to_idx) - self.prefix_query(from_idx - 1)

	def update(self, idx, add):
		idx += 1
		while idx <= self.n:
			self.array[idx] += add
			idx += idx & -idx

	def __str__(self):
		return ' '.join(map(str, self.array))
n = len(arr)
ma = max(arr)
lis = [0] * ma
bit = BIT(lis, ma)
ans = 0
for i in range(n):
	ans += bit.range_query(ma, arr[i] - 1)
	bit.update(arr[i] - 1, 1)
print(abs(ans))


from collections import defaultdict, deque
(n, s) = (int(input()), input())
fw = [0] * (n + 1)

def fw_add(fw, p, u):
	while p <= n:
		fw[p] += u
		p += p & -p

def fw_sum(fw, p):
	sm = 0
	while p > 0:
		sm += fw[p]
		p -= p & -p
	return sm
alpha = defaultdict(deque)
for (i, u) in enumerate(s):
	alpha[u].append(i + 1)
	fw_add(fw, i + 1, 1)
cc = 0
for u in reversed(s):
	p = alpha[u].popleft()
	cc += fw_sum(fw, p) - 1
	fw_add(fw, p, -1)
print(cc)


import sys, io, os
z = io.BytesIO(os.read(0, os.fstat(0).st_size)).readline
y = lambda o, c, l: range(o + (l - 1) * (1 - c), o + (l - 1) * (1 - c) + (2 * c - 1) * l, 2 * c - 1)

def f(x, g):
	l = len(x)
	if l < 2:
		return 0
	h = l // 2
	d = [[0] * 26 for i in [0] * 4]
	for i in range(h):
		d[0][x[i] - 97] += 1
		d[1][g[i] - 97] += 1
	for i in range(l - h):
		d[2][x[-1 - i] - 97] += 1
		d[3][g[-1 - i] - 97] += 1
	for i in range(26):
		if d[1][i] < d[0][i]:
			d[0][i] = d[1][i]
		if d[3][i] < d[2][i]:
			d[2][i] = d[3][i]
	(r1, t1, u1) = b(x, d[0], h, 1)
	(r2, t2, u2) = b(x, d[2], l - h, 0, h)
	return r1 + r2 + len(t1) * len(t2) + f(u1 + t2, g[:h]) + f(t1 + u2, g[h:])

def b(h, d, l, c, o=0):
	r = s = 0
	(w, u, t) = ([], [], [])
	for i in y(o, c, l):
		if d[h[i] - 97]:
			w.append(i)
			d[h[i] - 97] -= 1
			u.append(h[i])
	c = 1 - c
	for i in y(o, c, l):
		if w and i == w[-1]:
			w.pop()
			s += 1
		else:
			r += s
			t.append(h[i])
	if c < 1:
		t = t[::-1]
	else:
		u = u[::-1]
	return (r, t, u)
z()
m = z().strip()
print(f(m, m[::-1]))


import os, sys
from collections import defaultdict, Counter
from io import BytesIO, IOBase

def mergeSort(arr, n):
	temp_arr = [0] * n
	return _mergeSort(arr, temp_arr, 0, n - 1)

def _mergeSort(arr, temp_arr, left, right):
	inv_count = 0
	if left < right:
		mid = (left + right) // 2
		inv_count += _mergeSort(arr, temp_arr, left, mid)
		inv_count += _mergeSort(arr, temp_arr, mid + 1, right)
		inv_count += merge(arr, temp_arr, left, mid, right)
	return inv_count

def merge(arr, temp_arr, left, mid, right):
	i = left
	j = mid + 1
	k = left
	inv_count = 0
	while i <= mid and j <= right:
		if arr[i] <= arr[j]:
			temp_arr[k] = arr[i]
			k += 1
			i += 1
		else:
			temp_arr[k] = arr[j]
			inv_count += mid - i + 1
			k += 1
			j += 1
	while i <= mid:
		temp_arr[k] = arr[i]
		k += 1
		i += 1
	while j <= right:
		temp_arr[k] = arr[j]
		k += 1
		j += 1
	for loop_var in range(left, right + 1):
		arr[loop_var] = temp_arr[loop_var]
	return inv_count

def main():
	n = int(input())
	s = input()
	a = s[::-1]
	x = defaultdict(lambda : [])
	j = 1
	for i in a:
		x[i].append(j)
		j += 1
	for i in x:
		x[i].append(0)
	v = []
	for i in s:
		v.append(x[i][x[i][-1]])
		x[i][-1] += 1
	print(mergeSort(v, n))
BUFSIZE = 8192

class FastIO(IOBase):
	newlines = 0

	def __init__(self, file):
		self._fd = file.fileno()
		self.buffer = BytesIO()
		self.writable = 'x' in file.mode or 'r' not in file.mode
		self.write = self.buffer.write if self.writable else None

	def read(self):
		while True:
			b = os.read(self._fd, max(os.fstat(self._fd).st_size, BUFSIZE))
			if not b:
				break
			ptr = self.buffer.tell()
			(self.buffer.seek(0, 2), self.buffer.write(b), self.buffer.seek(ptr))
		self.newlines = 0
		return self.buffer.read()

	def readline(self):
		while self.newlines == 0:
			b = os.read(self._fd, max(os.fstat(self._fd).st_size, BUFSIZE))
			self.newlines = b.count(b'\n') + (not b)
			ptr = self.buffer.tell()
			(self.buffer.seek(0, 2), self.buffer.write(b), self.buffer.seek(ptr))
		self.newlines -= 1
		return self.buffer.readline()

	def flush(self):
		if self.writable:
			os.write(self._fd, self.buffer.getvalue())
			(self.buffer.truncate(0), self.buffer.seek(0))

class IOWrapper(IOBase):

	def __init__(self, file):
		self.buffer = FastIO(file)
		self.flush = self.buffer.flush
		self.writable = self.buffer.writable
		self.write = lambda s: self.buffer.write(s.encode('ascii'))
		self.read = lambda : self.buffer.read().decode('ascii')
		self.readline = lambda : self.buffer.readline().decode('ascii')
(sys.stdin, sys.stdout) = (IOWrapper(sys.stdin), IOWrapper(sys.stdout))
input = lambda : sys.stdin.readline().rstrip('\r\n')
main()


from collections import defaultdict

def merge(arr, temp, left, mid, right):
	inv = 0
	i = left
	j = mid
	k = left
	while i <= mid - 1 and j <= right:
		if arr[i] <= arr[j]:
			temp[k] = arr[i]
			k += 1
			i += 1
		else:
			temp[k] = arr[j]
			k += 1
			j += 1
			inv = inv + (mid - i)
	while i <= mid - 1:
		temp[k] = arr[i]
		k += 1
		i += 1
	while j <= right:
		temp[k] = arr[j]
		k += 1
		j += 1
	for i in range(left, right + 1, 1):
		arr[i] = temp[i]
	return inv

def Sort(arr, temp, left, right):
	inv = 0
	if right > left:
		mid = (right + left) // 2
		inv = Sort(arr, temp, left, mid)
		inv += Sort(arr, temp, mid + 1, right)
		inv += merge(arr, temp, left, mid + 1, right)
	return inv

def Swaps(arr, n):
	temp = [0 for i in range(n)]
	return Sort(arr, temp, 0, n - 1)
n = int(input())
s = input()
d = defaultdict(list)
freq = defaultdict(int)
rev = s[::-1]
lis = list()
for i in range(n):
	d[rev[i]].append(i)
for i in range(n):
	lis.append(d[s[i]][freq[s[i]]])
	freq[s[i]] += 1
print(Swaps(lis, n))


from sys import stdin, stdout
import math, sys, heapq
from itertools import permutations, combinations
from collections import defaultdict, deque, OrderedDict
from os import path
import random
import bisect as bi

def yes():
	print('YES')

def no():
	print('NO')
if path.exists('input.txt'):
	sys.stdin = open('input.txt', 'r')
	sys.stdout = open('output.txt', 'w')

	def I():
		return int(input())

	def In():
		return map(int, input().split())
else:

	def I():
		return int(stdin.readline())

	def In():
		return map(int, stdin.readline().split())

def dict(a):
	d = {}
	for x in a:
		if d.get(x, -1) != -1:
			d[x] += 1
		else:
			d[x] = 1
	return d

def find_gt(a, x):
	i = bi.bisect_left(a, x)
	if i != len(a):
		return i
	else:
		return -1

def update(bit, pos, val, n):
	while pos <= n:
		bit[pos] += val
		pos += pos & -pos

def calsum(bit, l, n):
	su = 0
	while l > 0:
		su += bit[l]
		l -= l & -l
	return su

def main():
	try:
		n = I()
		d = defaultdict(deque)
		S = input()
		for i in range(n):
			d[S[i]].append(i)
		reversal = []
		for i in range(n - 1, -1, -1):
			reversal.append(d[S[i]].popleft() + 1)
		bit = [0 for x in range(n + 2)]
		ans = 0
		for i in range(n - 1, -1, -1):
			ans += calsum(bit, reversal[i], n)
			update(bit, reversal[i], 1, n)
		print(ans)
	except:
		pass
M = 998244353
P = 1000000007
for _ in range(1):
	main()


import os
import sys
from io import BytesIO, IOBase
import heapq as h
from types import GeneratorType
BUFSIZE = 8192

class FastIO(IOBase):
	newlines = 0

	def __init__(self, file):
		import os
		self.os = os
		self._fd = file.fileno()
		self.buffer = BytesIO()
		self.writable = 'x' in file.mode or 'r' not in file.mode
		self.write = self.buffer.write if self.writable else None

	def read(self):
		while True:
			b = self.os.read(self._fd, max(self.os.fstat(self._fd).st_size, BUFSIZE))
			if not b:
				break
			ptr = self.buffer.tell()
			(self.buffer.seek(0, 2), self.buffer.write(b), self.buffer.seek(ptr))
		self.newlines = 0
		return self.buffer.read()

	def readline(self):
		while self.newlines == 0:
			b = self.os.read(self._fd, max(self.os.fstat(self._fd).st_size, BUFSIZE))
			self.newlines = b.count(b'\n') + (not b)
			ptr = self.buffer.tell()
			(self.buffer.seek(0, 2), self.buffer.write(b), self.buffer.seek(ptr))
		self.newlines -= 1
		return self.buffer.readline()

	def flush(self):
		if self.writable:
			self.os.write(self._fd, self.buffer.getvalue())
			(self.buffer.truncate(0), self.buffer.seek(0))

class IOWrapper(IOBase):

	def __init__(self, file):
		self.buffer = FastIO(file)
		self.flush = self.buffer.flush
		self.writable = self.buffer.writable
		self.write = lambda s: self.buffer.write(s.encode('ascii'))
		self.read = lambda : self.buffer.read().decode('ascii')
		self.readline = lambda : self.buffer.readline().decode('ascii')
(sys.stdin, sys.stdout) = (IOWrapper(sys.stdin), IOWrapper(sys.stdout))
input = lambda : sys.stdin.readline().rstrip('\r\n')
import time
start_time = time.time()
from collections import defaultdict as dd
import math
from functools import reduce

def getInts():
	return [int(s) for s in input().split()]

def getInt():
	return int(input())

def getStrs():
	return [s for s in input().split()]

def getStr():
	return input()

def listStr():
	return list(input())

def mergeSort(arr, n):
	temp_arr = [0] * n
	return _mergeSort(arr, temp_arr, 0, n - 1)

def _mergeSort(arr, temp_arr, left, right):
	inv_count = 0
	if left < right:
		mid = (left + right) // 2
		inv_count += _mergeSort(arr, temp_arr, left, mid)
		inv_count += _mergeSort(arr, temp_arr, mid + 1, right)
		inv_count += merge(arr, temp_arr, left, mid, right)
	return inv_count

def merge(arr, temp_arr, left, mid, right):
	i = left
	j = mid + 1
	k = left
	inv_count = 0
	while i <= mid and j <= right:
		if arr[i] <= arr[j]:
			temp_arr[k] = arr[i]
			k += 1
			i += 1
		else:
			temp_arr[k] = arr[j]
			inv_count += mid - i + 1
			k += 1
			j += 1
	while i <= mid:
		temp_arr[k] = arr[i]
		k += 1
		i += 1
	while j <= right:
		temp_arr[k] = arr[j]
		k += 1
		j += 1
	for loop_var in range(left, right + 1):
		arr[loop_var] = temp_arr[loop_var]
	return inv_count

def solve():
	N = getInt()
	S = listStr()
	T = S[::-1]
	arr = [-1] * N
	DS = dd(list)
	DT = dd(list)
	for (i, s) in enumerate(S):
		DS[s].append(i)
	for (i, s) in enumerate(T):
		DT[s].append(i)
	for s in DS:
		while DS[s]:
			(i1, i2) = (DS[s].pop(), DT[s].pop())
			arr[i1] = i2
	return mergeSort(arr, N)
print(solve())


from collections import defaultdict

class BIT:

	def __init__(self, n):
		self.n = n
		self.data = [0] * (n + 1)

	def to_sum(self, i):
		s = 0
		while i > 0:
			s += self.data[i]
			i -= i & -i
		return s

	def add(self, i, x):
		while i <= self.n:
			self.data[i] += x
			i += i & -i

	def get(self, i, j):
		return self.to_sum(j) - self.to_sum(i - 1)
N = int(input())
S = list(input())
reS = S[::-1]
alphabet = [chr(i) for i in range(ord('a'), ord('z') + 1)]
d = defaultdict(list)
red = defaultdict(list)
for (i, v) in enumerate(S):
	d[v].append(i)
for (i, v) in enumerate(reS):
	red[v].append(i)
seq = [-1] * (N + 1)
for (key, item) in d.items():
	Slist = d[key]
	reSlist = red[key]
	assert len(Slist) == len(reSlist)
	L = len(Slist)
	for i in range(L):
		seq[Slist[i] + 1] = reSlist[i] + 1
ans = 0
fenwick = BIT(200010)
for i in range(1, N + 1):
	v = seq[i]
	ans += fenwick.get(v + 1, 200010)
	fenwick.add(v, 1)
print(ans)


import os, sys
from io import BytesIO, IOBase
from collections import deque

def update(seg_tree, xx, u, v):
	curr = deque([(1, 1, xx)])
	while len(curr):
		x = curr.popleft()
		if x[1] >= u and x[2] <= v:
			seg_tree[x[0]] += 1
		elif not (u > x[2] or v < x[1]) and x[1] != x[2]:
			curr.append((x[0] * 2, x[1], (x[1] + x[2]) // 2))
			curr.append((x[0] * 2 + 1, (x[1] + x[2]) // 2 + 1, x[2]))

def traversal(seg_tree, xx, val):
	ans = 0
	curr = deque([(1, 1, xx)])
	while len(curr):
		x = curr.popleft()
		if x[1] == x[2] == val:
			ans += seg_tree[x[0]]
		elif x[1] <= val <= x[2]:
			ans += seg_tree[x[0]]
			curr.append((x[0] * 2, x[1], (x[1] + x[2]) // 2))
			curr.append((x[0] * 2 + 1, (x[1] + x[2]) // 2 + 1, x[2]))
	return ans

def main():
	n = int(input())
	s = input().strip()
	posi = [[] for _ in range(26)]
	for (ind, val) in enumerate(s):
		posi[ord(val) - 97].append(ind)
	for i in range(26):
		posi[i].reverse()
	tar = s[::-1]
	xx = 1 << n.bit_length()
	seg_tree = [0] * (2 * xx)
	ans = 0
	for (ind, val) in enumerate(tar):
		x = posi[ord(val) - 97].pop()
		y = traversal(seg_tree, xx, x)
		ans += x - y
		update(seg_tree, xx, x, xx)
	print(ans)
BUFSIZE = 8192

class FastIO(IOBase):
	newlines = 0

	def __init__(self, file):
		self._fd = file.fileno()
		self.buffer = BytesIO()
		self.writable = 'x' in file.mode or 'r' not in file.mode
		self.write = self.buffer.write if self.writable else None

	def read(self):
		while True:
			b = os.read(self._fd, max(os.fstat(self._fd).st_size, BUFSIZE))
			if not b:
				break
			ptr = self.buffer.tell()
			(self.buffer.seek(0, 2), self.buffer.write(b), self.buffer.seek(ptr))
		self.newlines = 0
		return self.buffer.read()

	def readline(self):
		while self.newlines == 0:
			b = os.read(self._fd, max(os.fstat(self._fd).st_size, BUFSIZE))
			self.newlines = b.count(b'\n') + (not b)
			ptr = self.buffer.tell()
			(self.buffer.seek(0, 2), self.buffer.write(b), self.buffer.seek(ptr))
		self.newlines -= 1
		return self.buffer.readline()

	def flush(self):
		if self.writable:
			os.write(self._fd, self.buffer.getvalue())
			(self.buffer.truncate(0), self.buffer.seek(0))

class IOWrapper(IOBase):

	def __init__(self, file):
		self.buffer = FastIO(file)
		self.flush = self.buffer.flush
		self.writable = self.buffer.writable
		self.write = lambda s: self.buffer.write(s.encode('ascii'))
		self.read = lambda : self.buffer.read().decode('ascii')
		self.readline = lambda : self.buffer.readline().decode('ascii')
(sys.stdin, sys.stdout) = (IOWrapper(sys.stdin), IOWrapper(sys.stdout))
input = lambda : sys.stdin.readline().rstrip('\r\n')
main()


import sys
import getpass
import math, random
import functools, itertools, collections, heapq, bisect
from collections import Counter, defaultdict, deque
input = sys.stdin.readline
M9 = 10 ** 9 + 7
(yes, no) = ('YES', 'NO')
MAXINT = sys.maxsize
OFFLINE_TEST = getpass.getuser() == 'hkmac'

def log(*args):
	if OFFLINE_TEST:
		print('\x1b[36m', *args, '\x1b[0m', file=sys.stderr)

def solve(*args):
	if OFFLINE_TEST:
		log('----- solving ------')
		log(*args)
		log('----- ------- ------')
	return solve_(*args)

def read_matrix(rows):
	return [list(map(int, input().split())) for _ in range(rows)]

def read_strings(rows):
	return [input().strip() for _ in range(rows)]

def minus_one(arr):
	return [x - 1 for x in arr]

def minus_one_matrix(mrr):
	return [[x - 1 for x in row] for row in mrr]

class FenwickTree:

	def __init__(self, bits=31):
		self.c = defaultdict(int)
		self.LARGE = 2 ** bits

	def update(self, x, increment):
		x += 1
		while x <= self.LARGE:
			self.c[x] += increment
			x += x & -x

	def query(self, x):
		x += 1
		res = 0
		while x > 0:
			res += self.c[x]
			x -= x & -x
		return res

def count_inversions(perm):
	res = 0
	t = FenwickTree(bits=len(bin(max(perm))))
	for (i, x) in enumerate(perm):
		cnt = t.query(x)
		res += i - cnt
		t.update(x, 1)
	return res

def solve_(srr):
	c1 = defaultdict(list)
	for (i, x) in enumerate(srr):
		c1[x].append(i)
	log(c1)
	locs = [-1] * len(srr)
	for (i, x) in reversed(list(enumerate(srr[::-1]))):
		locs[i] = c1[x].pop()
	log(locs)
	val = count_inversions(locs)
	return val
for case_num in [0]:
	k = int(input())
	srr = input().strip()
	res = solve(srr)
	print(res)


from sys import stdin
input = stdin.readline
from collections import defaultdict

class BIT:

	def __init__(self, n):
		self.n = n
		self.data = [0] * (n + 1)

	def add(self, i, x=1):
		i += 1
		while i <= self.n:
			self.data[i] += x
			i += i & -i

	def get_sum(self, i):
		i += 1
		x = 0
		while i > 0:
			x += self.data[i]
			i -= i & -i
		return x

def solve():
	n = int(input())
	s = input().strip()
	r = reversed(s)
	pos = defaultdict(list)
	for (i, v) in enumerate(s):
		pos[v].append(i)
	a = [0] * n
	index = {k: 0 for k in pos}
	for (i, v) in enumerate(r):
		a[i] = pos[v][index[v]]
		index[v] += 1
	bit = BIT(n)
	res = 0
	for i in range(n - 1, -1, -1):
		res += bit.get_sum(a[i])
		bit.add(a[i])
	print(res)
solve()


import sys
input = sys.stdin.readline

def segment_tree(ar, n):
	data = [0] * n + ar.copy()
	for i in range(n - 1, 0, -1):
		data[i] += data[i * 2] + data[i * 2 + 1]
	return data

def update(data, idx, n, value):
	idx += n
	data[idx] += value
	while idx > 1:
		idx //= 2
		data[idx] += value

def summation(data, l, r, n):
	l += n
	r += n
	maxi = 0
	while l < r:
		if l % 2 != 0:
			maxi += data[l]
			l += 1
		if r % 2 != 0:
			r -= 1
			maxi += data[r]
		l //= 2
		r //= 2
	return maxi
n = int(input())
st = list(input())[:-1]
ar = []
dic = {}
for i in range(n):
	ar.append(1)
	if st[i] in dic:
		dic[st[i]].append(i)
	else:
		dic[st[i]] = [i]
ar[0] = 0
for i in dic:
	dic[i] = dic[i][::-1]
rev = st[::-1]
data = segment_tree(ar, n)
ans = 0
for i in range(n):
	cur = rev[i]
	ind = dic[cur].pop()
	ind1 = summation(data, 0, ind + 1, n)
	tem = ind1 - i
	ans += tem
	if tem:
		update(data, 0, n, 1)
		update(data, ind, n, -ar[ind])
print(ans)


from bisect import *
from collections import *
from math import *
from heapq import *
from typing import List
from itertools import *
from operator import *
from functools import *
import os
import sys
from io import BytesIO, IOBase
BUFSIZE = 8192

class FastIO(IOBase):
	newlines = 0

	def __init__(self, file):
		self._fd = file.fileno()
		self.buffer = BytesIO()
		self.writable = 'x' in file.mode or 'r' not in file.mode
		self.write = self.buffer.write if self.writable else None

	def read(self):
		while True:
			b = os.read(self._fd, max(os.fstat(self._fd).st_size, BUFSIZE))
			if not b:
				break
			ptr = self.buffer.tell()
			(self.buffer.seek(0, 2), self.buffer.write(b), self.buffer.seek(ptr))
		self.newlines = 0
		return self.buffer.read()

	def readline(self):
		while self.newlines == 0:
			b = os.read(self._fd, max(os.fstat(self._fd).st_size, BUFSIZE))
			self.newlines = b.count(b'\n') + (not b)
			ptr = self.buffer.tell()
			(self.buffer.seek(0, 2), self.buffer.write(b), self.buffer.seek(ptr))
		self.newlines -= 1
		return self.buffer.readline()

	def flush(self):
		if self.writable:
			os.write(self._fd, self.buffer.getvalue())
			(self.buffer.truncate(0), self.buffer.seek(0))

class IOWrapper(IOBase):

	def __init__(self, file):
		self.buffer = FastIO(file)
		self.flush = self.buffer.flush
		self.writable = self.buffer.writable
		self.write = lambda s: self.buffer.write(s.encode('ascii'))
		self.read = lambda : self.buffer.read().decode('ascii')
		self.readline = lambda : self.buffer.readline().decode('ascii')
(sys.stdin, sys.stdout) = (IOWrapper(sys.stdin), IOWrapper(sys.stdout))
input = lambda : sys.stdin.readline().rstrip('\r\n')

def RL():
	return map(int, sys.stdin.readline().rstrip().split())

def RLL():
	return list(map(int, sys.stdin.readline().rstrip().split()))

def N():
	return int(input())

@lru_cache(None)
def fact(x):
	if x < 2:
		return 1
	return fact(x - 1) * x

@lru_cache(None)
def per(i, j):
	return fact(i) // fact(i - j)

@lru_cache(None)
def com(i, j):
	return per(i, j) // fact(j)

def linc(f, t, l, r):
	while l < r:
		mid = (l + r) // 2
		if t > f(mid):
			l = mid + 1
		else:
			r = mid
	return l

def rinc(f, t, l, r):
	while l < r:
		mid = (l + r + 1) // 2
		if t < f(mid):
			r = mid - 1
		else:
			l = mid
	return l

def ldec(f, t, l, r):
	while l < r:
		mid = (l + r) // 2
		if t < f(mid):
			l = mid + 1
		else:
			r = mid
	return l

def rdec(f, t, l, r):
	while l < r:
		mid = (l + r + 1) // 2
		if t > f(mid):
			r = mid - 1
		else:
			l = mid
	return l

def isprime(n):
	for i in range(2, int(n ** 0.5) + 1):
		if n % i == 0:
			return False
	return True

def binfun(x):
	c = 1
	res = 0
	for w in arr:
		res += w
		if res > x:
			res = w
		c += 1
	return c

def lowbit(n):
	return n & -n

class BIT:

	def __init__(self, arr):
		self.arr = arr
		self.n = len(arr) - 1

	def update(self, x, v):
		while x <= self.n:
			self.arr[x] += v
			x += x & -x

	def query(self, x):
		ans = 0
		while x:
			ans += self.arr[x]
			x &= x - 1
		return ans

class smt:

	def __init__(self, l, r, arr):
		self.l = l
		self.r = r
		self.value = (1 << 31) - 1 if l < r else arr[l]
		mid = (l + r) // 2
		if l < r:
			self.left = smt(l, mid, arr)
			self.right = smt(mid + 1, r, arr)
			self.value &= self.left.value & self.right.value

	def setvalue(self, x, val):
		if self.l == self.r:
			self.value = val
			return
		mid = (self.l + self.r) // 2
		if x <= mid:
			self.left.setvalue(x, val)
		else:
			self.right.setvalue(x, val)
		self.value = self.left.value & self.right.value

	def ask(self, l, r):
		if l <= self.l and r >= self.r:
			return self.value
		val = (1 << 31) - 1
		mid = (self.l + self.r) // 2
		if l <= mid:
			val &= self.left.ask(l, r)
		if r > mid:
			val &= self.right.ask(l, r)
		return val

class UFS:

	def __init__(self, n):
		self.parent = [i for i in range(n)]
		self.ranks = [0] * n

	def find(self, x):
		if x != self.parent[x]:
			self.parent[x] = self.find(self.parent[x])
		return self.parent[x]

	def union(self, u, v):
		(pu, pv) = (self.find(u), self.find(v))
		if pu == pv:
			return False
		if self.ranks[pu] >= self.ranks[pv]:
			self.parent[pv] = pu
			if self.ranks[pv] == self.ranks[pu]:
				self.ranks[pu] += 1
		else:
			self.parent[pu] = pv

def Prime(n):
	c = 0
	prime = []
	flag = [0] * (n + 1)
	for i in range(2, n + 1):
		if not flag[i]:
			prime.append(i)
			c += 1
		for j in range(c):
			if i * prime[j] > n:
				break
			flag[i * prime[j]] = prime[j]
			if i % prime[j] == 0:
				break
	return prime

def dij(s, graph):
	d = {}
	d[s] = 0
	heap = [(0, s)]
	seen = set()
	while heap:
		(dis, u) = heappop(heap)
		if u in seen:
			continue
		for v in graph[u]:
			if v not in d or d[v] > d[u] + graph[u][v]:
				d[v] = d[u] + graph[u][v]
				heappush(heap, (d[v], v))
	return d
n = N()
s = input()
bi = BIT([0] * (n + 1))
res = [deque() for _ in range(26)]
for (i, ch) in enumerate(s):
	res[ord(ch) - 97].append(i)
target = s[::-1]
ans = 0
for i in range(n):
	tmp = ord(target[i]) - 97
	ind = res[tmp].popleft()
	bind = n - ind
	move = bi.query(bind) + ind - i
	ans += move
	bi.update(bind, 1)
print(ans)


from os import path
import sys
from heapq import heappush, heappop
from functools import cmp_to_key as ctk
from collections import deque, defaultdict as dd
from bisect import bisect, bisect_left, bisect_right, insort, insort_left, insort_right
from itertools import permutations
from datetime import datetime
from math import ceil, sqrt, log, gcd

def ii():
	return int(input())

def si():
	return input().rstrip()

def mi():
	return map(int, input().split())

def li():
	return list(mi())
abc = 'abcdefghijklmnopqrstuvwxyz'
mod = 998244353
inf = float('inf')
vow = ['a', 'e', 'i', 'o', 'u']
(dx, dy) = ([-1, 1, 0, 0], [0, 0, 1, -1])

def bo(i):
	return ord(i) - ord('a')

def solve():
	n = ii()
	s = si()
	p = []
	rev_s = list(s[:])
	rev_s.reverse()
	tmp = [[] for i in range(26)]
	for i in range(n):
		tmp[bo(rev_s[i])].append(i)
	for i in range(26):
		tmp[i].reverse()
	for i in range(n):
		p.append(tmp[bo(s[i])][-1])
		tmp[bo(s[i])].pop()
	tmp = [0] * n

	def merge(l, mid, r):
		(i1, i2, inv_cnt, k) = (l, mid + 1, 0, l)
		while i1 <= mid and i2 <= r:
			if p[i1] <= p[i2]:
				tmp[k] = p[i1]
				i1 += 1
			else:
				tmp[k] = p[i2]
				i2 += 1
				inv_cnt += mid - i1 + 1
			k += 1
		while i1 <= mid:
			tmp[k] = p[i1]
			k += 1
			i1 += 1
		while i2 <= r:
			tmp[k] = p[i2]
			k += 1
			i2 += 1
		for i in range(l, r + 1):
			p[i] = tmp[i]
		return inv_cnt

	def mergesort(l, r):
		inv_cnt = 0
		if l < r:
			mid = l + r >> 1
			inv_cnt += mergesort(l, mid)
			inv_cnt += mergesort(mid + 1, r)
			inv_cnt += merge(l, mid, r)
		return inv_cnt
	print(mergesort(0, n - 1))
if path.exists('input.txt'):
	sys.stdin = open('input.txt', 'r')
	sys.stdout = open('output.txt', 'w')
else:
	input = sys.stdin.readline
solve()


from pprint import pprint

def do():

	class segmentTreeSum:
		initValue = 0
		dat = []
		lenTreeList = -1
		depthTreeList = 0
		lenOriginalList = -1

		def __init__(self):
			pass

		def load(self, l):
			self.lenOriginalList = len(l)
			self.lenTreeList = 2 ** (len(l) - 1).bit_length()
			self.depthTreeList = (len(l) - 1).bit_length()
			self.dat = [self.initValue] * (self.lenTreeList * 2)
			for i in range(len(l)):
				self.dat[self.lenTreeList - 1 + i] = l[i]
			self.build()

		def build(self):
			for i in range(self.lenTreeList - 2, -1, -1):
				self.dat[i] = self.dat[2 * i + 1] + self.dat[2 * i + 2]

		def addValue(self, i, a):
			nodeId = self.lenTreeList - 1 + i
			self.dat[nodeId] += a
			self.setValue(i, self.dat[nodeId])

		def setValue(self, i, a):
			nodeId = self.lenTreeList - 1 + i
			self.dat[nodeId] = a
			while nodeId != 0:
				nodeId = (nodeId - 1) // 2
				self.dat[nodeId] = self.dat[nodeId * 2 + 1] + self.dat[nodeId * 2 + 2]

		def querySub(self, a, b, nodeId, l, r):
			if r <= a or b <= l:
				return self.initValue
			if a <= l and r <= b:
				return self.dat[nodeId]
			resLeft = self.querySub(a, b, 2 * nodeId + 1, l, (l + r) // 2)
			resRight = self.querySub(a, b, 2 * nodeId + 2, (l + r) // 2, r)
			return resLeft + resRight

		def query(self, a, b):
			return self.querySub(a, b, 0, 0, self.lenTreeList)

		def findNthValueSub(self, x, nodeId):
			if self.dat[nodeId] < x:
				return (None, x - self.dat[nodeId])
			if nodeId >= self.lenTreeList - 1:
				return (True, nodeId - (self.lenTreeList - 1))
			resLeft = self.findNthValueSub(x, 2 * nodeId + 1)
			if resLeft[0] != None:
				return (True, resLeft[1])
			resRight = self.findNthValueSub(resLeft[1], 2 * nodeId + 2)
			return resRight

		def findNthValue(self, x):
			return self.findNthValueSub(x, 0)[1]
	charpos = []
	for i in range(26):
		charpos.append([])
	charused = [0] * 26
	n = int(input())
	s = input()
	l = [0] * n
	st = segmentTreeSum()
	st.load(l)
	st.build()
	targets = s[::-1]
	s = list(s)
	for i in range(n):
		x = ord(s[i]) - ord('a')
		charpos[x].append(i)
	res = 0
	for i in range(n):
		tx = ord(targets[i]) - ord('a')
		used = charused[tx]
		originalpos = charpos[tx][used]
		st.setValue(originalpos, 1)
		charused[tx] += 1
		originalpos += st.query(originalpos + 1, n)
		d = originalpos - i
		if d > 0:
			res += d
	print(res)
do()


class SegmentTree:

	def __init__(self, arr, func):
		self.f = func
		self.N = len(arr)
		self.tree = [0 for _ in range(4 * self.N)]
		for i in range(self.N):
			self.tree[self.N + i] = arr[i]
		for i in range(self.N - 1, 0, -1):
			self.tree[i] = self.f(self.tree[i << 1], self.tree[i << 1 | 1])

	def updateTreeNode(self, idx, value):
		self.tree[idx + self.N] = value
		idx += self.N
		i = idx
		while i > 1:
			self.tree[i >> 1] = self.f(self.tree[i], self.tree[i ^ 1])
			i >>= 1

	def query(self, l, r):
		r += 1
		res = 0
		l += self.N
		r += self.N
		while l < r:
			if l & 1:
				res = self.f(res, self.tree[l])
				l += 1
			if r & 1:
				r -= 1
				res = self.f(res, self.tree[r])
			l >>= 1
			r >>= 1
		return res
from collections import defaultdict

def main():
	n = int(input())
	s = input()
	characterIndices = defaultdict(lambda : [])
	for (i, c) in enumerate(s):
		characterIndices[c].append(i)
	removedCountsSegTree = SegmentTree([0 for _ in range(n)], lambda a, b: a + b)
	ans = 0
	target = s[::-1]
	for i in range(n - 1, -1, -1):
		requiredChar = target[i]
		latestIdx = characterIndices[requiredChar].pop()
		nMoves = i - latestIdx + removedCountsSegTree.query(0, latestIdx)
		ans += nMoves
		removedCountsSegTree.updateTreeNode(latestIdx, 1)
	print(ans)
	return
import sys
input = lambda : sys.stdin.readline().rstrip('\r\n')

def oneLineArrayPrint(arr):
	print(' '.join([str(x) for x in arr]))

def multiLineArrayPrint(arr):
	print('\n'.join([str(x) for x in arr]))

def multiLineArrayOfArraysPrint(arr):
	print('\n'.join([' '.join([str(x) for x in y]) for y in arr]))
main()


import os
import sys
from io import BytesIO, IOBase
from collections import deque
BUFSIZE = 8192

class FastIO(IOBase):
	newlines = 0

	def __init__(self, file):
		self._fd = file.fileno()
		self.buffer = BytesIO()
		self.writable = 'x' in file.mode or 'r' not in file.mode
		self.write = self.buffer.write if self.writable else None

	def read(self):
		while True:
			b = os.read(self._fd, max(os.fstat(self._fd).st_size, BUFSIZE))
			if not b:
				break
			ptr = self.buffer.tell()
			(self.buffer.seek(0, 2), self.buffer.write(b), self.buffer.seek(ptr))
		self.newlines = 0
		return self.buffer.read()

	def readline(self):
		while self.newlines == 0:
			b = os.read(self._fd, max(os.fstat(self._fd).st_size, BUFSIZE))
			self.newlines = b.count(b'\n') + (not b)
			ptr = self.buffer.tell()
			(self.buffer.seek(0, 2), self.buffer.write(b), self.buffer.seek(ptr))
		self.newlines -= 1
		return self.buffer.readline()

	def flush(self):
		if self.writable:
			os.write(self._fd, self.buffer.getvalue())
			(self.buffer.truncate(0), self.buffer.seek(0))

class IOWrapper(IOBase):

	def __init__(self, file):
		self.buffer = FastIO(file)
		self.flush = self.buffer.flush
		self.writable = self.buffer.writable
		self.write = lambda s: self.buffer.write(s.encode('ascii'))
		self.read = lambda : self.buffer.read().decode('ascii')
		self.readline = lambda : self.buffer.readline().decode('ascii')
(sys.stdin, sys.stdout) = (IOWrapper(sys.stdin), IOWrapper(sys.stdout))

def input():
	return sys.stdin.readline().rstrip('\r\n')

def getint():
	return int(input())

def getints():
	return list(map(int, input().split()))

def getint1():
	return list(map(lambda x: int(x) - 1, input().split()))

def merge(arr, l, h):
	if h - l == 1:
		return
	mid = (l + h) // 2
	merge(arr, l, mid)
	merge(arr, mid, h)
	msort(arr, l, mid, h)
	return

def msort(arr, l, mid, h):
	global count
	left = arr[l:mid]
	right = arr[mid:h]
	(i, j, k) = (0, 0, 0)
	leftlimit = mid - l
	rightlimit = h - mid
	while i < leftlimit and j < rightlimit:
		if left[i] <= right[j]:
			arr[k + l] = left[i]
			i += 1
		else:
			arr[k + l] = right[j]
			j += 1
			count += mid - l - i
		k += 1
	while i < leftlimit:
		arr[k + l] = left[i]
		i += 1
		k += 1
	while j < rightlimit:
		arr[k + l] = right[j]
		j += 1
		k += 1

def main():
	n = int(input())
	s = input()
	t = s[::-1]
	s1 = {}
	t1 = {}
	visit = [-1] * n
	for i in range(n):
		if s[i] in s1:
			s1[s[i]].append(i)
			t1[s[i]].append(n - i - 1)
		else:
			s1[s[i]] = deque([i])
			t1[s[i]] = deque([n - i - 1])
	for i in s1:
		while s1[i]:
			pos1 = s1[i].popleft()
			pos2 = t1[i].pop()
			visit[pos1] = pos2
	merge(visit, 0, n)
	print(count)
count = 0
main()


import sys
input = sys.stdin.readline
n = int(input())
s = input().rstrip()

class FenwickTree:

	def __init__(self, n):
		self.t = [0] * (n + 1)

	def update(self, i, x):
		i += 1
		while i < len(self.t):
			self.t[i] += x
			i += i & -i

	def query(self, r):
		ans = 0
		while r:
			ans += self.t[r]
			r -= r & -r
		return ans
rev = s[::-1]
indices = [[] for _ in range(26)]

def ind(x):
	return ord(x) - ord('a')
for (i, x) in enumerate(s):
	indices[ind(x)].append(i)
for x in indices:
	x.reverse()
ft = FenwickTree(n)
for i in range(n):
	ft.update(i, 1)
ans = 0
for x in rev:
	ans += ft.query(indices[ind(x)][-1])
	ft.update(indices[ind(x)][-1], -1)
	indices[ind(x)].pop()
print(ans)


from collections import deque

def update(arr, i):
	while i <= n:
		arr[i] += 1
		i += i & -i

def qsum(x):
	sm = 0
	while x > 0:
		sm += arr[x]
		x -= x & -x
	return sm
n = int(input())
s = input()
t = s[::-1]
posi = [deque([]) for i in range(26)]
for i in range(n):
	posi[ord(t[i]) - ord('a')].append(i + 1)
ls = []
for i in range(n):
	ls.append(posi[ord(s[i]) - ord('a')].popleft())
res = 0
arr = [0] * (n + 1)
for num in ls:
	res += qsum(n) - qsum(num)
	update(arr, num)
print(res)


class BIT(object):

	def __init__(self, nums):
		n = len(nums)
		self.ori = nums
		self.tree = [0] * n

	def update(self, index, incre):
		j = index
		while j < len(self.ori):
			self.tree[j] += incre
			j += j + 1 & -j - 1

	def getsum(self, index):
		j = index
		output = 0
		while j >= 0:
			output += self.tree[j]
			j -= j + 1 & -j - 1
		return output
import bisect
n = int(input())
index = [[] for i in range(26)]
s = input()
for i in range(n):
	index[ord(s[i]) - 97].append(i)
for i in range(26):
	index[i] = index[i][::-1]
rev = s[::-1]
temp = []
tree = [0] * n
tree = BIT(tree)
ans = 0
for i in range(n):
	num = index[ord(rev[i]) - 97].pop()
	loc = BIT.getsum(tree, num)
	ans += num - loc
	BIT.update(tree, num, 1)
print(ans)


import os
import sys
from io import BytesIO, IOBase
BUFSIZE = 8192

class FastIO(IOBase):
	newlines = 0

	def __init__(self, file):
		self._fd = file.fileno()
		self.buffer = BytesIO()
		self.writable = 'x' in file.mode or 'r' not in file.mode
		self.write = self.buffer.write if self.writable else None

	def read(self):
		while True:
			b = os.read(self._fd, max(os.fstat(self._fd).st_size, BUFSIZE))
			if not b:
				break
			ptr = self.buffer.tell()
			(self.buffer.seek(0, 2), self.buffer.write(b), self.buffer.seek(ptr))
		self.newlines = 0
		return self.buffer.read()

	def readline(self):
		while self.newlines == 0:
			b = os.read(self._fd, max(os.fstat(self._fd).st_size, BUFSIZE))
			self.newlines = b.count(b'\n') + (not b)
			ptr = self.buffer.tell()
			(self.buffer.seek(0, 2), self.buffer.write(b), self.buffer.seek(ptr))
		self.newlines -= 1
		return self.buffer.readline()

	def flush(self):
		if self.writable:
			os.write(self._fd, self.buffer.getvalue())
			(self.buffer.truncate(0), self.buffer.seek(0))

class IOWrapper(IOBase):

	def __init__(self, file):
		self.buffer = FastIO(file)
		self.flush = self.buffer.flush
		self.writable = self.buffer.writable
		self.write = lambda s: self.buffer.write(s.encode('ascii'))
		self.read = lambda : self.buffer.read().decode('ascii')
		self.readline = lambda : self.buffer.readline().decode('ascii')
(sys.stdin, sys.stdout) = (IOWrapper(sys.stdin), IOWrapper(sys.stdout))
input = lambda : sys.stdin.readline().rstrip('\r\n')

def RL():
	return map(int, sys.stdin.readline().rstrip().split())

def RLL():
	return list(map(int, sys.stdin.readline().rstrip().split()))

def N():
	return int(input())

def print_list(l):
	print(' '.join(map(str, l)))
from collections import defaultdict as dc

def reversePairs(nums):
	if not nums:
		return 0
	res = 0

	def merge(a, b):
		nonlocal res
		temp = []
		(i, j) = (0, 0)
		m = len(a)
		n = len(b)
		while i < m and j < n:
			if a[i] <= b[j]:
				temp.append(a[i])
				i += 1
			else:
				temp.append(b[j])
				j += 1
				res += m - i
		if i < m:
			temp += a[i:]
		else:
			temp += b[j:]
		return temp

	def mergesort(L):
		length = len(L)
		if length == 1:
			return L
		k = length >> 1
		a = mergesort(L[:k])
		b = mergesort(L[k:])
		return merge(a, b)
	mergesort(nums)
	return res
n = N()
s = input()
t = s[::-1]
res = 0
flag = [0] * n
dic = dc(int)
for i in range(n):
	c = t[i]
	key = s.find(c, dic[c])
	dic[c] = key + 1
	flag[key] = i
print(reversePairs(flag))


import sys
input = sys.stdin.readline
from collections import deque
n = int(input())
s = list(input().strip())
d = dict()
for i in range(n - 1, -1, -1):
	if s[i] in d:
		d[s[i]].append(n - i - 1)
	else:
		d[s[i]] = deque([n - i - 1])
lis = [-1] * n
for i in range(n):
	lis[i] = d[s[i]].popleft()

def merge(a, b):
	i = j = ans = 0
	(n, m) = (len(a), len(b))
	c = []
	while i < n and j < m:
		if a[i] <= b[j]:
			c.append(a[i])
			i += 1
		else:
			c.append(b[j])
			j += 1
			ans += n - i
	while i < n:
		c.append(a[i])
		i += 1
	while j < m:
		c.append(b[j])
		j += 1
	return (c, ans)

def mergeSort(lis):
	p = len(lis)
	if p in (0, 1):
		return (lis, 0)
	mid = p // 2
	(a, v1) = mergeSort(lis[:mid])
	(b, v2) = mergeSort(lis[mid:])
	(c, v3) = merge(a, b)
	return (c, v1 + v2 + v3)
(_, ans) = mergeSort(lis)
print(ans)


def mergeSortswap(arr):
	if len(arr) > 1:
		mid = len(arr) // 2
		L = arr[:mid]
		R = arr[mid:]
		x = mergeSortswap(L)
		y = mergeSortswap(R)
		i = j = k = 0
		z = 0
		while i < len(L) and j < len(R):
			if L[i] < R[j]:
				arr[k] = L[i]
				i += 1
			else:
				arr[k] = R[j]
				z += mid - i
				j += 1
			k += 1
		while i < len(L):
			arr[k] = L[i]
			i += 1
			k += 1
		while j < len(R):
			arr[k] = R[j]
			j += 1
			k += 1
		return z + x + y
	else:
		return 0
import collections, bisect
n = int(input())
s = input().strip(' ')
d = collections.defaultdict(collections.deque)
s_reverse = s[::-1]
if s == s_reverse:
	print(0)
else:
	for i in range(n):
		d[s_reverse[i]].append(i)
	to_sort = []
	for i in range(n):
		ind = d[s[i]].popleft()
		to_sort.append(ind)
	c = mergeSortswap(to_sort)
	print(c)


import sys
input = sys.stdin.readline

def inversions(x):
	if len(x) == 1:
		return (x, 0)
	(a, b, both) = (x[:len(x) // 2], x[len(x) // 2:], [])
	(a, a_inv) = inversions(a)
	(b, b_inv) = inversions(b)
	(inv, i, j) = (a_inv + b_inv, 0, 0)
	while i < len(a) and j < len(b):
		if a[i] <= b[j]:
			both.append(a[i])
			i += 1
		else:
			both.append(b[j])
			j += 1
			inv += len(a) - i
	both += a[i:]
	both += b[j:]
	return (both, inv)
(n, s, pos, swaps) = (int(input()), input().strip()[::-1], {i: [] for i in range(26)}, 0)
for i in range(n):
	pos[ord(s[i]) - ord('a')].append(i)
order = [pos[ord(s[i]) - ord('a')].pop() for i in range(n)][::-1]
print(inversions(order)[1])


class BIT:

	def __init__(self, n):
		self.n = n
		self.data = [0] * (n + 1)

	def to_sum(self, i):
		s = 0
		while i > 0:
			s += self.data[i]
			i -= i & -i
		return s

	def add(self, i, x):
		while i <= self.n:
			self.data[i] += x
			i += i & -i

	def get(self, i, j):
		return self.to_sum(j) - self.to_sum(i - 1)

def main():
	n = int(input())
	s = input()
	b = s[::-1]
	alphabet = list('abcdefghijklmnopqrstuvwxyz')
	before = {v: [] for v in alphabet}
	after = {v: [] for v in alphabet}
	for i in range(n):
		before[s[i]].append(i)
		after[b[i]].append(i)
	data = []
	for v in alphabet:
		M = len(before[v])
		for j in range(M):
			(old, new) = (before[v][j], after[v][j])
			data.append((old, new + 1))
	data.sort(reverse=True)
	ans = 0
	bit = BIT(n)
	for (x, v) in data:
		ans += bit.to_sum(v)
		bit.add(v, 1)
	print(ans)
	return
main()