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.

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.

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

NoteIn 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.

package main

import (
	"bufio"
	"fmt"
	"os"
)

var _r = bufio.NewReader(os.Stdin)
var _w = bufio.NewWriter(os.Stdout)

var n int
var s []byte

const maxn int = 2e5 + 7

var bitTree [maxn]int

func lowbit(x int) int {
	return x & (-x)
}

func modify(pos int, val int) {
	for ; pos <= n; pos += lowbit(pos) {
		bitTree[pos] += val
	}
}

func query(pos int) (res int) {
	for ; pos > 0; pos -= lowbit(pos) {
		res += bitTree[pos]
	}
	return
}

func sum(l int, r int) int {
	return query(r) - query(l-1)
}

func main() {
	_, _ = fmt.Fscan(_r, &n, &s)
	t := make([]byte, n)
	for i, i2 := range s {
		t[n-1-i] = i2
	}
	pos := [26][]int{}
	for i, i2 := range t {
		pos[i2-'a'] = append(pos[i2-'a'], i)
	}
	var p []int
	for _, i2 := range s {
		p = append(p, pos[i2-'a'][0]+1)
		pos[i2-'a'] = pos[i2-'a'][1:]
	}
	ans := int64(0)
	for _, i2 := range p {
		ans += int64(sum(i2+1, n))
		modify(i2,1)
	}
	fmt.Println(ans)
}

/*
URL:
https://codeforces.com/contest/1430/problem/E
*/

package main

import (
	"bufio"
	"fmt"
	"io"
	"math"
	"os"
	"strconv"
)

func Reverse(A []rune) []rune {
	res := []rune{}

	n := len(A)
	for i := n - 1; i >= 0; i-- {
		res = append(res, A[i])
	}

	return res
}

var (
	n int
	S []rune

	U [30][]int
)

func main() {
	defer stdout.Flush()

	n = readi()
	S = readrs()

	for i := 0; i < n; i++ {
		c := S[i] - 'a'
		U[c] = append(U[c], i)
	}

	f := func(lv, rv T) T {
		return lv + rv
	}
	g := func(to T, from E) T {
		return to + T(from)
	}
	h := func(to, from E) E {
		return to + from
	}
	p := func(e E, length int) E {
		return e * E(length)
	}
	ti := T(0)
	ei := E(0)
	lst := NewLazySegmentTree(n, f, g, h, p, ti, ei)

	ans := int64(0)
	revS := Reverse(S)

	if string(S) == string(revS) {
		printf("0\n")
		return
	}

	for i := 0; i < n; i++ {
		c := revS[i] - 'a'

		idx := U[c][0]
		U[c] = U[c][1:] // 捨てる

		plus := int(lst.Query(idx, idx+1))
		j := idx + plus

		ans += int64(j - i)

		lst.Update(0, idx, E(1))
	}

	printf("%d\n", ans)
}

// Assumption: T == E
type T int // (T, f): Monoid
type E int // (E, h): Operator Monoid

type LazySegmentTree struct {
	sz   int
	data []T
	lazy []E
	f    func(lv, rv T) T        // T <> T -> T
	g    func(to T, from E) T    // T <> E -> T (assignment operator)
	h    func(to, from E) E      // E <> E -> E (assignment operator)
	p    func(e E, length int) E // E <> N -> E
	ti   T
	ei   E
}

func NewLazySegmentTree(
	n int,
	f func(lv, rv T) T, g func(to T, from E) T,
	h func(to, from E) E, p func(e E, length int) E,
	ti T, ei E,
) *LazySegmentTree {
	lst := new(LazySegmentTree)
	lst.f, lst.g, lst.h, lst.p = f, g, h, p
	lst.ti, lst.ei = ti, ei

	lst.sz = 1
	for lst.sz < n {
		lst.sz *= 2
	}

	lst.data = make([]T, 2*lst.sz-1)
	lst.lazy = make([]E, 2*lst.sz-1)
	for i := 0; i < 2*lst.sz-1; i++ {
		lst.data[i] = lst.ti
		lst.lazy[i] = lst.ei
	}

	return lst
}

func (lst *LazySegmentTree) Set(k int, x T) {
	lst.data[k+(lst.sz-1)] = x
}

func (lst *LazySegmentTree) Build() {
	for i := lst.sz - 2; i >= 0; i-- {
		lst.data[i] = lst.f(lst.data[2*i+1], lst.data[2*i+2])
	}
}

func (lst *LazySegmentTree) propagate(k, length int) {
	if lst.lazy[k] != lst.ei {
		if k < lst.sz-1 {
			lst.lazy[2*k+1] = lst.h(lst.lazy[2*k+1], lst.lazy[k])
			lst.lazy[2*k+2] = lst.h(lst.lazy[2*k+2], lst.lazy[k])
		}
		lst.data[k] = lst.g(lst.data[k], lst.p(lst.lazy[k], length))
		lst.lazy[k] = lst.ei
	}
}

func (lst *LazySegmentTree) Update(a, b int, x E) T {
	return lst.update(a, b, x, 0, 0, lst.sz)
}

func (lst *LazySegmentTree) update(a, b int, x E, k, l, r int) T {
	lst.propagate(k, r-l)

	if r <= a || b <= l {
		return lst.data[k]
	}

	if a <= l && r <= b {
		lst.lazy[k] = lst.h(lst.lazy[k], x)
		lst.propagate(k, r-l)
		return lst.data[k]
	}

	lv := lst.update(a, b, x, 2*k+1, l, (l+r)/2)
	rv := lst.update(a, b, x, 2*k+2, (l+r)/2, r)
	lst.data[k] = lst.f(lv, rv)
	return lst.data[k]
}

func (lst *LazySegmentTree) Query(a, b int) T {
	return lst.query(a, b, 0, 0, lst.sz)
}

func (lst *LazySegmentTree) query(a, b, k, l, r int) T {
	lst.propagate(k, r-l)

	if r <= a || b <= l {
		return lst.ti
	}

	if a <= l && r <= b {
		return lst.data[k]
	}

	lv := lst.query(a, b, 2*k+1, l, (l+r)/2)
	rv := lst.query(a, b, 2*k+2, (l+r)/2, r)
	return lst.f(lv, rv)
}

func (lst *LazySegmentTree) Get(k int) T {
	return lst.Query(k, k+1)
}

/*******************************************************************/

/********** common constants **********/

const (
	MOD = 1000000000 + 7
	// MOD          = 998244353
	ALPH_N  = 26
	INF_I64 = math.MaxInt64
	INF_B60 = 1 << 60
	INF_I32 = math.MaxInt32
	INF_B30 = 1 << 30
	NIL     = -1
	EPS     = 1e-10
)

/********** bufio setting **********/

func init() {
	// bufio.ScanWords <---> bufio.ScanLines
	reads = newReadString(os.Stdin, bufio.ScanWords)
	stdout = bufio.NewWriter(os.Stdout)
}

// mod can calculate a right residual whether value is positive or negative.
func mod(val, m int) int {
	res := val % m
	if res < 0 {
		res += m
	}
	return res
}

// min returns the min integer among input set.
// This function needs at least 1 argument (no argument causes panic).
func min(integers ...int) int {
	m := integers[0]
	for i, integer := range integers {
		if i == 0 {
			continue
		}
		if m > integer {
			m = integer
		}
	}
	return m
}

// max returns the max integer among input set.
// This function needs at least 1 argument (no argument causes panic).
func max(integers ...int) int {
	m := integers[0]
	for i, integer := range integers {
		if i == 0 {
			continue
		}
		if m < integer {
			m = integer
		}
	}
	return m
}

// chmin accepts a pointer of integer and a target value.
// If target value is SMALLER than the first argument,
//	then the first argument will be updated by the second argument.
func chmin(updatedValue *int, target int) bool {
	if *updatedValue > target {
		*updatedValue = target
		return true
	}
	return false
}

// chmax accepts a pointer of integer and a target value.
// If target value is LARGER than the first argument,
//	then the first argument will be updated by the second argument.
func chmax(updatedValue *int, target int) bool {
	if *updatedValue < target {
		*updatedValue = target
		return true
	}
	return false
}

// sum returns multiple integers sum.
func sum(integers ...int) int {
	var s int
	s = 0

	for _, i := range integers {
		s += i
	}

	return s
}

/********** FAU standard libraries **********/

//fmt.Sprintf("%b\n", 255) 	// binary expression

/********** I/O usage **********/

//str := reads()
//i := readi()
//X := readis(n)
//S := readrs()
//a := readf()
//A := readfs(n)

//str := ZeroPaddingRuneSlice(num, 32)
//str := PrintIntsLine(X...)

/*********** Input ***********/

var (
	// reads returns a WORD string.
	reads  func() string
	stdout *bufio.Writer
)

func newReadString(ior io.Reader, sf bufio.SplitFunc) func() string {
	r := bufio.NewScanner(ior)
	r.Buffer(make([]byte, 1024), int(1e+9)) // for Codeforces
	r.Split(sf)

	return func() string {
		if !r.Scan() {
			panic("Scan failed")
		}
		return r.Text()
	}
}

// readi returns an integer.
func readi() int {
	return int(_readInt64())
}
func readi2() (int, int) {
	return int(_readInt64()), int(_readInt64())
}
func readi3() (int, int, int) {
	return int(_readInt64()), int(_readInt64()), int(_readInt64())
}
func readi4() (int, int, int, int) {
	return int(_readInt64()), int(_readInt64()), int(_readInt64()), int(_readInt64())
}

// readll returns as integer as int64.
func readll() int64 {
	return _readInt64()
}
func readll2() (int64, int64) {
	return _readInt64(), _readInt64()
}
func readll3() (int64, int64, int64) {
	return _readInt64(), _readInt64(), _readInt64()
}
func readll4() (int64, int64, int64, int64) {
	return _readInt64(), _readInt64(), _readInt64(), _readInt64()
}

func _readInt64() int64 {
	i, err := strconv.ParseInt(reads(), 0, 64)
	if err != nil {
		panic(err.Error())
	}
	return i
}

// readis returns an integer slice that has n integers.
func readis(n int) []int {
	b := make([]int, n)
	for i := 0; i < n; i++ {
		b[i] = readi()
	}
	return b
}

// readlls returns as int64 slice that has n integers.
func readlls(n int) []int64 {
	b := make([]int64, n)
	for i := 0; i < n; i++ {
		b[i] = readll()
	}
	return b
}

// readf returns an float64.
func readf() float64 {
	return float64(_readFloat64())
}

func _readFloat64() float64 {
	f, err := strconv.ParseFloat(reads(), 64)
	if err != nil {
		panic(err.Error())
	}
	return f
}

// ReadFloatSlice returns an float64 slice that has n float64.
func readfs(n int) []float64 {
	b := make([]float64, n)
	for i := 0; i < n; i++ {
		b[i] = readf()
	}
	return b
}

// readrs returns a rune slice.
func readrs() []rune {
	return []rune(reads())
}

/*********** Output ***********/

// PrintIntsLine returns integers string delimited by a space.
func PrintIntsLine(A ...int) string {
	res := []rune{}

	for i := 0; i < len(A); i++ {
		str := strconv.Itoa(A[i])
		res = append(res, []rune(str)...)

		if i != len(A)-1 {
			res = append(res, ' ')
		}
	}

	return string(res)
}

// PrintIntsLine returns integers string delimited by a space.
func PrintInts64Line(A ...int64) string {
	res := []rune{}

	for i := 0; i < len(A); i++ {
		str := strconv.FormatInt(A[i], 10) // 64bit int version
		res = append(res, []rune(str)...)

		if i != len(A)-1 {
			res = append(res, ' ')
		}
	}

	return string(res)
}

// Printf is function for output strings to buffered os.Stdout.
// You may have to call stdout.Flush() finally.
func printf(format string, a ...interface{}) {
	fmt.Fprintf(stdout, format, a...)
}

/*********** Debugging ***********/

// debugf is wrapper of fmt.Fprintf(os.Stderr, format, a...)
func debugf(format string, a ...interface{}) {
	fmt.Fprintf(os.Stderr, format, a...)
}

// ZeroPaddingRuneSlice returns binary expressions of integer n with zero padding.
// For debugging use.
func ZeroPaddingRuneSlice(n, digitsNum int) []rune {
	sn := fmt.Sprintf("%b", n)

	residualLength := digitsNum - len(sn)
	if residualLength <= 0 {
		return []rune(sn)
	}

	zeros := make([]rune, residualLength)
	for i := 0; i < len(zeros); i++ {
		zeros[i] = '0'
	}

	res := []rune{}
	res = append(res, zeros...)
	res = append(res, []rune(sn)...)

	return res
}

/*
URL:
https://codeforces.com/contest/1430/problem/E
*/

package main

import (
	"bufio"
	"fmt"
	"io"
	"math"
	"os"
	"strconv"
)

func Reverse(A []rune) []rune {
	res := []rune{}

	n := len(A)
	for i := n - 1; i >= 0; i-- {
		res = append(res, A[i])
	}

	return res
}

var (
	n int
	S []rune

	C [30][]int
)

func main() {
	defer stdout.Flush()

	n = readi()
	S = readrs()
	revS := Reverse(S)

	for i, rr := range S {
		r := rr - 'a'
		C[r] = append(C[r], i)
	}

	A := []int{}
	for _, rr := range revS {
		r := rr - 'a'
		A = append(A, C[r][0])
		C[r] = C[r][1:]
	}

	ans := InversionNumber(A)

	fmt.Println(ans)
}

type FenwickTree struct {
	dat     []int
	n       int
	minPow2 int
}

// n(>=1) is number of elements of original data
func NewFenwickTree(n int) *FenwickTree {
	ft := new(FenwickTree)

	ft.dat = make([]int, n+1)
	ft.n = n

	ft.minPow2 = 1
	for {
		if (ft.minPow2 << 1) > n {
			break
		}
		ft.minPow2 <<= 1
	}

	return ft
}

// Add x to i.
// i is 0-index.
func (ft *FenwickTree) Add(i int, x int) {
	ft._add(i+1, x)
}

// RangeSum calculates a range sum of [l, r).
// l, r are 0-index.
func (ft *FenwickTree) RangeSum(l, r int) int {
	res := ft._cumsum(r) - ft._cumsum(l)

	return res
}

// LowerBound returns minimum i such that bit.Sum(i) >= w.
// LowerBound returns n, if the total sum is less than w.
func (ft *FenwickTree) LowerBound(w int) int {
	if w <= 0 {
		return 0
	}

	x := 0
	for k := ft.minPow2; k > 0; k /= 2 {
		if x+k <= ft.n && ft.dat[x+k] < w {
			w -= ft.dat[x+k]
			x += k
		}
	}

	return x
}

// private: Sum of [1, i](1-based)
func (ft *FenwickTree) _cumsum(i int) int {
	s := 0

	for i > 0 {
		s += ft.dat[i]
		i -= i & (-i)
	}

	return s
}

// private: Add x to i(1-based)
func (ft *FenwickTree) _add(i, x int) {
	for i <= ft.n {
		ft.dat[i] += x
		i += i & (-i)
	}
}

// InversionNumber returns 転倒数 of slice A.
// Time complexity: O(NlogN)
func InversionNumber(A []int) (res int64) {
	_max := func(integers ...int) int {
		m := integers[0]
		for i, integer := range integers {
			if i == 0 {
				continue
			}
			if m < integer {
				m = integer
			}
		}
		return m
	}

	res = 0

	maximum := _max(A...)
	ft := NewFenwickTree(maximum + 1)

	for i := 0; i < len(A); i++ {
		res += int64(i - ft.RangeSum(0, A[i]+1))
		ft.Add(A[i], 1)
	}

	return res
}

/*******************************************************************/

/********** common constants **********/

const (
	MOD = 1000000000 + 7
	// MOD          = 998244353
	ALPH_N  = 26
	INF_I64 = math.MaxInt64
	INF_B60 = 1 << 60
	INF_I32 = math.MaxInt32
	INF_B30 = 1 << 30
	NIL     = -1
	EPS     = 1e-10
)

/********** bufio setting **********/

func init() {
	// bufio.ScanWords <---> bufio.ScanLines
	reads = newReadString(os.Stdin, bufio.ScanWords)
	stdout = bufio.NewWriter(os.Stdout)
}

// mod can calculate a right residual whether value is positive or negative.
func mod(val, m int) int {
	res := val % m
	if res < 0 {
		res += m
	}
	return res
}

// min returns the min integer among input set.
// This function needs at least 1 argument (no argument causes panic).
func min(integers ...int) int {
	m := integers[0]
	for i, integer := range integers {
		if i == 0 {
			continue
		}
		if m > integer {
			m = integer
		}
	}
	return m
}

// max returns the max integer among input set.
// This function needs at least 1 argument (no argument causes panic).
func max(integers ...int) int {
	m := integers[0]
	for i, integer := range integers {
		if i == 0 {
			continue
		}
		if m < integer {
			m = integer
		}
	}
	return m
}

// chmin accepts a pointer of integer and a target value.
// If target value is SMALLER than the first argument,
//	then the first argument will be updated by the second argument.
func chmin(updatedValue *int, target int) bool {
	if *updatedValue > target {
		*updatedValue = target
		return true
	}
	return false
}

// chmax accepts a pointer of integer and a target value.
// If target value is LARGER than the first argument,
//	then the first argument will be updated by the second argument.
func chmax(updatedValue *int, target int) bool {
	if *updatedValue < target {
		*updatedValue = target
		return true
	}
	return false
}

// sum returns multiple integers sum.
func sum(integers ...int) int {
	var s int
	s = 0

	for _, i := range integers {
		s += i
	}

	return s
}

/********** FAU standard libraries **********/

//fmt.Sprintf("%b\n", 255) 	// binary expression

/********** I/O usage **********/

//str := reads()
//i := readi()
//X := readis(n)
//S := readrs()
//a := readf()
//A := readfs(n)

//str := ZeroPaddingRuneSlice(num, 32)
//str := PrintIntsLine(X...)

/*********** Input ***********/

var (
	// reads returns a WORD string.
	reads  func() string
	stdout *bufio.Writer
)

func newReadString(ior io.Reader, sf bufio.SplitFunc) func() string {
	r := bufio.NewScanner(ior)
	r.Buffer(make([]byte, 1024), int(1e+9)) // for Codeforces
	r.Split(sf)

	return func() string {
		if !r.Scan() {
			panic("Scan failed")
		}
		return r.Text()
	}
}

// readi returns an integer.
func readi() int {
	return int(_readInt64())
}
func readi2() (int, int) {
	return int(_readInt64()), int(_readInt64())
}
func readi3() (int, int, int) {
	return int(_readInt64()), int(_readInt64()), int(_readInt64())
}
func readi4() (int, int, int, int) {
	return int(_readInt64()), int(_readInt64()), int(_readInt64()), int(_readInt64())
}

// readll returns as integer as int64.
func readll() int64 {
	return _readInt64()
}
func readll2() (int64, int64) {
	return _readInt64(), _readInt64()
}
func readll3() (int64, int64, int64) {
	return _readInt64(), _readInt64(), _readInt64()
}
func readll4() (int64, int64, int64, int64) {
	return _readInt64(), _readInt64(), _readInt64(), _readInt64()
}

func _readInt64() int64 {
	i, err := strconv.ParseInt(reads(), 0, 64)
	if err != nil {
		panic(err.Error())
	}
	return i
}

// readis returns an integer slice that has n integers.
func readis(n int) []int {
	b := make([]int, n)
	for i := 0; i < n; i++ {
		b[i] = readi()
	}
	return b
}

// readlls returns as int64 slice that has n integers.
func readlls(n int) []int64 {
	b := make([]int64, n)
	for i := 0; i < n; i++ {
		b[i] = readll()
	}
	return b
}

// readf returns an float64.
func readf() float64 {
	return float64(_readFloat64())
}

func _readFloat64() float64 {
	f, err := strconv.ParseFloat(reads(), 64)
	if err != nil {
		panic(err.Error())
	}
	return f
}

// ReadFloatSlice returns an float64 slice that has n float64.
func readfs(n int) []float64 {
	b := make([]float64, n)
	for i := 0; i < n; i++ {
		b[i] = readf()
	}
	return b
}

// readrs returns a rune slice.
func readrs() []rune {
	return []rune(reads())
}

/*********** Output ***********/

// PrintIntsLine returns integers string delimited by a space.
func PrintIntsLine(A ...int) string {
	res := []rune{}

	for i := 0; i < len(A); i++ {
		str := strconv.Itoa(A[i])
		res = append(res, []rune(str)...)

		if i != len(A)-1 {
			res = append(res, ' ')
		}
	}

	return string(res)
}

// PrintIntsLine returns integers string delimited by a space.
func PrintInts64Line(A ...int64) string {
	res := []rune{}

	for i := 0; i < len(A); i++ {
		str := strconv.FormatInt(A[i], 10) // 64bit int version
		res = append(res, []rune(str)...)

		if i != len(A)-1 {
			res = append(res, ' ')
		}
	}

	return string(res)
}

// Printf is function for output strings to buffered os.Stdout.
// You may have to call stdout.Flush() finally.
func printf(format string, a ...interface{}) {
	fmt.Fprintf(stdout, format, a...)
}

/*********** Debugging ***********/

// debugf is wrapper of fmt.Fprintf(os.Stderr, format, a...)
func debugf(format string, a ...interface{}) {
	fmt.Fprintf(os.Stderr, format, a...)
}

// ZeroPaddingRuneSlice returns binary expressions of integer n with zero padding.
// For debugging use.
func ZeroPaddingRuneSlice(n, digitsNum int) []rune {
	sn := fmt.Sprintf("%b", n)

	residualLength := digitsNum - len(sn)
	if residualLength <= 0 {
		return []rune(sn)
	}

	zeros := make([]rune, residualLength)
	for i := 0; i < len(zeros); i++ {
		zeros[i] = '0'
	}

	res := []rune{}
	res = append(res, zeros...)
	res = append(res, []rune(sn)...)

	return res
}

/*
URL:
https://codeforces.com/contest/1430/problem/E
*/

package main

import (
	"bufio"
	"fmt"
	"io"
	"math"
	"os"
	"strconv"
)

func Reverse(A []rune) []rune {
	res := []rune{}

	n := len(A)
	for i := n - 1; i >= 0; i-- {
		res = append(res, A[i])
	}

	return res
}

var (
	n int
	S []rune

	C [30][]int
)

func main() {
	defer stdout.Flush()

	n = readi()
	S = readrs()
	revS := Reverse(S)

	for i, rr := range S {
		r := rr - 'a'
		C[r] = append(C[r], i)
	}

	A := []int{}
	for _, rr := range revS {
		r := rr - 'a'
		A = append(A, C[r][0])
		C[r] = C[r][1:]
	}

	ans := InversionNumber(A)

	fmt.Println(ans)
}

func InversionNumber(A []int) int64 {
	var res int64
	res = 0

	ft := NewFenwickTree(len(A))
	for i := 0; i < len(A); i++ {
		res += int64(i - ft.RangeSum(0, A[i]))
		ft.Add(A[i], 1)
	}

	return res
}

type FenwickTree struct {
	dat     []int
	n       int
	minPow2 int
}

// n(>=1) is number of elements of original data
func NewFenwickTree(n int) *FenwickTree {
	ft := new(FenwickTree)

	ft.dat = make([]int, n+1)
	ft.n = n

	ft.minPow2 = 1
	for {
		if (ft.minPow2 << 1) > n {
			break
		}
		ft.minPow2 <<= 1
	}

	return ft
}

// Add x to i.
// i is 0-index.
func (ft *FenwickTree) Add(i int, x int) {
	ft._add(i+1, x)
}

// RangeSum calculates a range sum of [l, r).
// l, r are 0-index.
func (ft *FenwickTree) RangeSum(l, r int) int {
	res := ft._cumsum(r) - ft._cumsum(l)

	return res
}

// LowerBound returns minimum i such that bit.Sum(i) >= w.
// LowerBound returns n, if the total sum is less than w.
func (ft *FenwickTree) LowerBound(w int) int {
	if w <= 0 {
		return 0
	}

	x := 0
	for k := ft.minPow2; k > 0; k /= 2 {
		if x+k <= ft.n && ft.dat[x+k] < w {
			w -= ft.dat[x+k]
			x += k
		}
	}

	return x
}

// private: Sum of [1, i](1-based)
func (ft *FenwickTree) _cumsum(i int) int {
	s := 0

	for i > 0 {
		s += ft.dat[i]
		i -= i & (-i)
	}

	return s
}

// private: Add x to i(1-based)
func (ft *FenwickTree) _add(i, x int) {
	for i <= ft.n {
		ft.dat[i] += x
		i += i & (-i)
	}
}

/*******************************************************************/

/********** common constants **********/

const (
	MOD = 1000000000 + 7
	// MOD          = 998244353
	ALPH_N  = 26
	INF_I64 = math.MaxInt64
	INF_B60 = 1 << 60
	INF_I32 = math.MaxInt32
	INF_B30 = 1 << 30
	NIL     = -1
	EPS     = 1e-10
)

/********** bufio setting **********/

func init() {
	// bufio.ScanWords <---> bufio.ScanLines
	reads = newReadString(os.Stdin, bufio.ScanWords)
	stdout = bufio.NewWriter(os.Stdout)
}

// mod can calculate a right residual whether value is positive or negative.
func mod(val, m int) int {
	res := val % m
	if res < 0 {
		res += m
	}
	return res
}

// min returns the min integer among input set.
// This function needs at least 1 argument (no argument causes panic).
func min(integers ...int) int {
	m := integers[0]
	for i, integer := range integers {
		if i == 0 {
			continue
		}
		if m > integer {
			m = integer
		}
	}
	return m
}

// max returns the max integer among input set.
// This function needs at least 1 argument (no argument causes panic).
func max(integers ...int) int {
	m := integers[0]
	for i, integer := range integers {
		if i == 0 {
			continue
		}
		if m < integer {
			m = integer
		}
	}
	return m
}

// chmin accepts a pointer of integer and a target value.
// If target value is SMALLER than the first argument,
//	then the first argument will be updated by the second argument.
func chmin(updatedValue *int, target int) bool {
	if *updatedValue > target {
		*updatedValue = target
		return true
	}
	return false
}

// chmax accepts a pointer of integer and a target value.
// If target value is LARGER than the first argument,
//	then the first argument will be updated by the second argument.
func chmax(updatedValue *int, target int) bool {
	if *updatedValue < target {
		*updatedValue = target
		return true
	}
	return false
}

// sum returns multiple integers sum.
func sum(integers ...int) int {
	var s int
	s = 0

	for _, i := range integers {
		s += i
	}

	return s
}

/********** FAU standard libraries **********/

//fmt.Sprintf("%b\n", 255) 	// binary expression

/********** I/O usage **********/

//str := reads()
//i := readi()
//X := readis(n)
//S := readrs()
//a := readf()
//A := readfs(n)

//str := ZeroPaddingRuneSlice(num, 32)
//str := PrintIntsLine(X...)

/*********** Input ***********/

var (
	// reads returns a WORD string.
	reads  func() string
	stdout *bufio.Writer
)

func newReadString(ior io.Reader, sf bufio.SplitFunc) func() string {
	r := bufio.NewScanner(ior)
	r.Buffer(make([]byte, 1024), int(1e+9)) // for Codeforces
	r.Split(sf)

	return func() string {
		if !r.Scan() {
			panic("Scan failed")
		}
		return r.Text()
	}
}

// readi returns an integer.
func readi() int {
	return int(_readInt64())
}
func readi2() (int, int) {
	return int(_readInt64()), int(_readInt64())
}
func readi3() (int, int, int) {
	return int(_readInt64()), int(_readInt64()), int(_readInt64())
}
func readi4() (int, int, int, int) {
	return int(_readInt64()), int(_readInt64()), int(_readInt64()), int(_readInt64())
}

// readll returns as integer as int64.
func readll() int64 {
	return _readInt64()
}
func readll2() (int64, int64) {
	return _readInt64(), _readInt64()
}
func readll3() (int64, int64, int64) {
	return _readInt64(), _readInt64(), _readInt64()
}
func readll4() (int64, int64, int64, int64) {
	return _readInt64(), _readInt64(), _readInt64(), _readInt64()
}

func _readInt64() int64 {
	i, err := strconv.ParseInt(reads(), 0, 64)
	if err != nil {
		panic(err.Error())
	}
	return i
}

// readis returns an integer slice that has n integers.
func readis(n int) []int {
	b := make([]int, n)
	for i := 0; i < n; i++ {
		b[i] = readi()
	}
	return b
}

// readlls returns as int64 slice that has n integers.
func readlls(n int) []int64 {
	b := make([]int64, n)
	for i := 0; i < n; i++ {
		b[i] = readll()
	}
	return b
}

// readf returns an float64.
func readf() float64 {
	return float64(_readFloat64())
}

func _readFloat64() float64 {
	f, err := strconv.ParseFloat(reads(), 64)
	if err != nil {
		panic(err.Error())
	}
	return f
}

// ReadFloatSlice returns an float64 slice that has n float64.
func readfs(n int) []float64 {
	b := make([]float64, n)
	for i := 0; i < n; i++ {
		b[i] = readf()
	}
	return b
}

// readrs returns a rune slice.
func readrs() []rune {
	return []rune(reads())
}

/*********** Output ***********/

// PrintIntsLine returns integers string delimited by a space.
func PrintIntsLine(A ...int) string {
	res := []rune{}

	for i := 0; i < len(A); i++ {
		str := strconv.Itoa(A[i])
		res = append(res, []rune(str)...)

		if i != len(A)-1 {
			res = append(res, ' ')
		}
	}

	return string(res)
}

// PrintIntsLine returns integers string delimited by a space.
func PrintInts64Line(A ...int64) string {
	res := []rune{}

	for i := 0; i < len(A); i++ {
		str := strconv.FormatInt(A[i], 10) // 64bit int version
		res = append(res, []rune(str)...)

		if i != len(A)-1 {
			res = append(res, ' ')
		}
	}

	return string(res)
}

// Printf is function for output strings to buffered os.Stdout.
// You may have to call stdout.Flush() finally.
func printf(format string, a ...interface{}) {
	fmt.Fprintf(stdout, format, a...)
}

/*********** Debugging ***********/

// debugf is wrapper of fmt.Fprintf(os.Stderr, format, a...)
func debugf(format string, a ...interface{}) {
	fmt.Fprintf(os.Stderr, format, a...)
}

// ZeroPaddingRuneSlice returns binary expressions of integer n with zero padding.
// For debugging use.
func ZeroPaddingRuneSlice(n, digitsNum int) []rune {
	sn := fmt.Sprintf("%b", n)

	residualLength := digitsNum - len(sn)
	if residualLength <= 0 {
		return []rune(sn)
	}

	zeros := make([]rune, residualLength)
	for i := 0; i < len(zeros); i++ {
		zeros[i] = '0'
	}

	res := []rune{}
	res = append(res, zeros...)
	res = append(res, []rune(sn)...)

	return res
}

/*
URL:
https://codeforces.com/contest/1430/problem/E
*/

package main

import (
	"bufio"
	"fmt"
	"io"
	"math"
	"os"
	"strconv"
)

func Reverse(A []rune) []rune {
	res := []rune{}

	n := len(A)
	for i := n - 1; i >= 0; i-- {
		res = append(res, A[i])
	}

	return res
}

var (
	n int
	S []rune

	U [30][]int
)

func main() {
	defer stdout.Flush()

	n = readi()
	S = readrs()

	for i := 0; i < n; i++ {
		c := S[i] - 'a'
		U[c] = append(U[c], i)
	}

	f := func(lv, rv T) T {
		return lv + rv
	}
	g := func(to T, from E) T {
		return to + T(from)
	}
	h := func(to, from E) E {
		return to + from
	}
	p := func(e E, length int) E {
		return e * E(length)
	}
	ti := T(0)
	ei := E(0)
	lst := NewLazySegmentTree(n, f, g, h, p, ti, ei)

	// ans := 0
	ans := int64(0)
	revS := Reverse(S)

	if string(S) == string(revS) {
		printf("0\n")
		return
	}

	for i := 0; i < n; i++ {
		c := revS[i] - 'a'

		idx := U[c][0]
		U[c] = U[c][1:] // 捨てる

		// plus := ft.RangeSum(0, idx)
		plus := int(lst.Query(idx, idx+1))
		j := idx + plus

		// ans += j - i
		ans += int64(j - i)
		// debugf("%d: %d\n", i, j-i)

		// if idx-1 >= 0 {
		// ft.Add(j-1, 1)
		lst.Update(0, idx, E(1))
		// }
	}

	printf("%d\n", ans)
}

// Assumption: T == E
type T int // (T, f): Monoid
type E int // (E, h): Operator Monoid

type LazySegmentTree struct {
	sz   int
	data []T
	lazy []E
	f    func(lv, rv T) T        // T <> T -> T
	g    func(to T, from E) T    // T <> E -> T (assignment operator)
	h    func(to, from E) E      // E <> E -> E (assignment operator)
	p    func(e E, length int) E // E <> N -> E
	ti   T
	ei   E
}

func NewLazySegmentTree(
	n int,
	f func(lv, rv T) T, g func(to T, from E) T,
	h func(to, from E) E, p func(e E, length int) E,
	ti T, ei E,
) *LazySegmentTree {
	lst := new(LazySegmentTree)
	lst.f, lst.g, lst.h, lst.p = f, g, h, p
	lst.ti, lst.ei = ti, ei

	lst.sz = 1
	for lst.sz < n {
		lst.sz *= 2
	}

	lst.data = make([]T, 2*lst.sz-1)
	lst.lazy = make([]E, 2*lst.sz-1)
	for i := 0; i < 2*lst.sz-1; i++ {
		lst.data[i] = lst.ti
		lst.lazy[i] = lst.ei
	}

	return lst
}

func (lst *LazySegmentTree) Set(k int, x T) {
	lst.data[k+(lst.sz-1)] = x
}

func (lst *LazySegmentTree) Build() {
	for i := lst.sz - 2; i >= 0; i-- {
		lst.data[i] = lst.f(lst.data[2*i+1], lst.data[2*i+2])
	}
}

func (lst *LazySegmentTree) propagate(k, length int) {
	if lst.lazy[k] != lst.ei {
		if k < lst.sz-1 {
			lst.lazy[2*k+1] = lst.h(lst.lazy[2*k+1], lst.lazy[k])
			lst.lazy[2*k+2] = lst.h(lst.lazy[2*k+2], lst.lazy[k])
		}
		lst.data[k] = lst.g(lst.data[k], lst.p(lst.lazy[k], length))
		lst.lazy[k] = lst.ei
	}
}

func (lst *LazySegmentTree) Update(a, b int, x E) T {
	return lst.update(a, b, x, 0, 0, lst.sz)
}

func (lst *LazySegmentTree) update(a, b int, x E, k, l, r int) T {
	lst.propagate(k, r-l)

	if r <= a || b <= l {
		return lst.data[k]
	}

	if a <= l && r <= b {
		lst.lazy[k] = lst.h(lst.lazy[k], x)
		lst.propagate(k, r-l)
		return lst.data[k]
	}

	lv := lst.update(a, b, x, 2*k+1, l, (l+r)/2)
	rv := lst.update(a, b, x, 2*k+2, (l+r)/2, r)
	lst.data[k] = lst.f(lv, rv)
	return lst.data[k]
}

func (lst *LazySegmentTree) Query(a, b int) T {
	return lst.query(a, b, 0, 0, lst.sz)
}

func (lst *LazySegmentTree) query(a, b, k, l, r int) T {
	lst.propagate(k, r-l)

	if r <= a || b <= l {
		return lst.ti
	}

	if a <= l && r <= b {
		return lst.data[k]
	}

	lv := lst.query(a, b, 2*k+1, l, (l+r)/2)
	rv := lst.query(a, b, 2*k+2, (l+r)/2, r)
	return lst.f(lv, rv)
}

func (lst *LazySegmentTree) Get(k int) T {
	return lst.Query(k, k+1)
}

/*******************************************************************/

/********** common constants **********/

const (
	MOD = 1000000000 + 7
	// MOD          = 998244353
	ALPH_N  = 26
	INF_I64 = math.MaxInt64
	INF_B60 = 1 << 60
	INF_I32 = math.MaxInt32
	INF_B30 = 1 << 30
	NIL     = -1
	EPS     = 1e-10
)

/********** bufio setting **********/

func init() {
	// bufio.ScanWords <---> bufio.ScanLines
	reads = newReadString(os.Stdin, bufio.ScanWords)
	stdout = bufio.NewWriter(os.Stdout)
}

// mod can calculate a right residual whether value is positive or negative.
func mod(val, m int) int {
	res := val % m
	if res < 0 {
		res += m
	}
	return res
}

// min returns the min integer among input set.
// This function needs at least 1 argument (no argument causes panic).
func min(integers ...int) int {
	m := integers[0]
	for i, integer := range integers {
		if i == 0 {
			continue
		}
		if m > integer {
			m = integer
		}
	}
	return m
}

// max returns the max integer among input set.
// This function needs at least 1 argument (no argument causes panic).
func max(integers ...int) int {
	m := integers[0]
	for i, integer := range integers {
		if i == 0 {
			continue
		}
		if m < integer {
			m = integer
		}
	}
	return m
}

// chmin accepts a pointer of integer and a target value.
// If target value is SMALLER than the first argument,
//	then the first argument will be updated by the second argument.
func chmin(updatedValue *int, target int) bool {
	if *updatedValue > target {
		*updatedValue = target
		return true
	}
	return false
}

// chmax accepts a pointer of integer and a target value.
// If target value is LARGER than the first argument,
//	then the first argument will be updated by the second argument.
func chmax(updatedValue *int, target int) bool {
	if *updatedValue < target {
		*updatedValue = target
		return true
	}
	return false
}

// sum returns multiple integers sum.
func sum(integers ...int) int {
	var s int
	s = 0

	for _, i := range integers {
		s += i
	}

	return s
}

/********** FAU standard libraries **********/

//fmt.Sprintf("%b\n", 255) 	// binary expression

/********** I/O usage **********/

//str := reads()
//i := readi()
//X := readis(n)
//S := readrs()
//a := readf()
//A := readfs(n)

//str := ZeroPaddingRuneSlice(num, 32)
//str := PrintIntsLine(X...)

/*********** Input ***********/

var (
	// reads returns a WORD string.
	reads  func() string
	stdout *bufio.Writer
)

func newReadString(ior io.Reader, sf bufio.SplitFunc) func() string {
	r := bufio.NewScanner(ior)
	r.Buffer(make([]byte, 1024), int(1e+9)) // for Codeforces
	r.Split(sf)

	return func() string {
		if !r.Scan() {
			panic("Scan failed")
		}
		return r.Text()
	}
}

// readi returns an integer.
func readi() int {
	return int(_readInt64())
}
func readi2() (int, int) {
	return int(_readInt64()), int(_readInt64())
}
func readi3() (int, int, int) {
	return int(_readInt64()), int(_readInt64()), int(_readInt64())
}
func readi4() (int, int, int, int) {
	return int(_readInt64()), int(_readInt64()), int(_readInt64()), int(_readInt64())
}

// readll returns as integer as int64.
func readll() int64 {
	return _readInt64()
}
func readll2() (int64, int64) {
	return _readInt64(), _readInt64()
}
func readll3() (int64, int64, int64) {
	return _readInt64(), _readInt64(), _readInt64()
}
func readll4() (int64, int64, int64, int64) {
	return _readInt64(), _readInt64(), _readInt64(), _readInt64()
}

func _readInt64() int64 {
	i, err := strconv.ParseInt(reads(), 0, 64)
	if err != nil {
		panic(err.Error())
	}
	return i
}

// readis returns an integer slice that has n integers.
func readis(n int) []int {
	b := make([]int, n)
	for i := 0; i < n; i++ {
		b[i] = readi()
	}
	return b
}

// readlls returns as int64 slice that has n integers.
func readlls(n int) []int64 {
	b := make([]int64, n)
	for i := 0; i < n; i++ {
		b[i] = readll()
	}
	return b
}

// readf returns an float64.
func readf() float64 {
	return float64(_readFloat64())
}

func _readFloat64() float64 {
	f, err := strconv.ParseFloat(reads(), 64)
	if err != nil {
		panic(err.Error())
	}
	return f
}

// ReadFloatSlice returns an float64 slice that has n float64.
func readfs(n int) []float64 {
	b := make([]float64, n)
	for i := 0; i < n; i++ {
		b[i] = readf()
	}
	return b
}

// readrs returns a rune slice.
func readrs() []rune {
	return []rune(reads())
}

/*********** Output ***********/

// PrintIntsLine returns integers string delimited by a space.
func PrintIntsLine(A ...int) string {
	res := []rune{}

	for i := 0; i < len(A); i++ {
		str := strconv.Itoa(A[i])
		res = append(res, []rune(str)...)

		if i != len(A)-1 {
			res = append(res, ' ')
		}
	}

	return string(res)
}

// PrintIntsLine returns integers string delimited by a space.
func PrintInts64Line(A ...int64) string {
	res := []rune{}

	for i := 0; i < len(A); i++ {
		str := strconv.FormatInt(A[i], 10) // 64bit int version
		res = append(res, []rune(str)...)

		if i != len(A)-1 {
			res = append(res, ' ')
		}
	}

	return string(res)
}

// Printf is function for output strings to buffered os.Stdout.
// You may have to call stdout.Flush() finally.
func printf(format string, a ...interface{}) {
	fmt.Fprintf(stdout, format, a...)
}

/*********** Debugging ***********/

// debugf is wrapper of fmt.Fprintf(os.Stderr, format, a...)
func debugf(format string, a ...interface{}) {
	fmt.Fprintf(os.Stderr, format, a...)
}

// ZeroPaddingRuneSlice returns binary expressions of integer n with zero padding.
// For debugging use.
func ZeroPaddingRuneSlice(n, digitsNum int) []rune {
	sn := fmt.Sprintf("%b", n)

	residualLength := digitsNum - len(sn)
	if residualLength <= 0 {
		return []rune(sn)
	}

	zeros := make([]rune, residualLength)
	for i := 0; i < len(zeros); i++ {
		zeros[i] = '0'
	}

	res := []rune{}
	res = append(res, zeros...)
	res = append(res, []rune(sn)...)

	return res
}

package main

import (
	"bufio"
	. "fmt"
	"io"
	"os"
)

// github.com/EndlessCheng/codeforces-go
func CF1430E(_r io.Reader, out io.Writer) {
	var n int
	var s []byte
	Fscan(bufio.NewReader(_r), &n, &s)
	tree := make([]int, n+1)
	add := func(i int) {
		for ; i <= n; i += i & -i {
			tree[i]++
		}
	}
	sum := func(i int) (res int) {
		for ; i > 0; i &= i - 1 {
			res += tree[i]
		}
		return
	}
	query := func(l, r int) int { return sum(r) - sum(l-1) }

	posS := [26][]int{}
	t := make([]byte, n)
	for i, b := range s {
		b -= 'a'
		t[n-1-i] = b
		posS[b] = append(posS[b], i)
	}
	ans := int64(0)
	for i, b := range t {
		p := posS[b][0]
		posS[b] = posS[b][1:]
		ans += int64(p + query(p+1, n) - i)
		add(p + 1)
	}
	Fprint(out, ans)
}

func main() { CF1430E(os.Stdin, os.Stdout) }

package main

import (
	"bufio"
	. "fmt"
	"io"
	"os"
)

type fenwick struct {
	tree []int
}

func newFenwickTree(n int) fenwick {
	return fenwick{make([]int, n+1)}
}
func (f fenwick) add(i int, val int) {
	i++
	for ; i < len(f.tree); i += i & -i {
		f.tree[i] += val
	}
}
func (f fenwick) sum(i int) (res int) {
	i++
	for ; i > 0; i &= i - 1 {
		res += f.tree[i]
	}
	return
}
func (f fenwick) query(l, r int) (res int) { // [l,r]
	return f.sum(r) - f.sum(l-1)
}

// github.com/EndlessCheng/codeforces-go
func run(_r io.Reader, _w io.Writer) {
	in := bufio.NewReader(_r)
	out := bufio.NewWriter(_w)
	defer out.Flush()

	var n int
	var s []byte
	Fscan(in, &n, &s)

	posS := [26][]int{}
	t := make([]byte, n)
	for i, b := range s {
		b -= 'a'
		t[n-1-i] = b
		posS[b] = append(posS[b], i)
	}

	//posT := [26][]int{}
	//for i, b := range t {
	//	posT[b] = append(posT[b], i)
	//}

	f := newFenwickTree(n)
	ans := int64(0)
	for i, b := range t {
		ps := posS[b][0]
		posS[b] = posS[b][1:]

		delta := f.query(ps, n-1)
		ans += int64(ps + delta - i)

		f.add(ps, 1)
	}
	Fprintln(out, ans)
}

func main() { run(os.Stdin, os.Stdout) }

package main

import (
	"bufio"
	"errors"
	"fmt"
	"os"
)

var reader = bufio.NewReader(os.Stdin)

func main() {
	var n int
	fmt.Fscan(reader, &n)

	var s string
	fmt.Fscan(reader, &s)

	runeMap := [26][]int{}
	for i := n - 1; i >= 0; i-- {
		r := s[i] - 'a'
		runeMap[r] = append(runeMap[r], n-i-1)
	}

	pos := []int{}
	for _, r := range s {
		v := runeMap[r-'a'][0]
		runeMap[r-'a'] = runeMap[r-'a'][1:]
		pos = append(pos, v)
	}

	var swaps int64
	f := New(n)
	for i := n - 1; i >= 0; i-- {
		swaps += f.Sum(0, pos[i])
		f.Add(pos[i], 1)
	}

	fmt.Println(swaps)
}

type Fenwick struct {
	data []int
}

func New(size int) *Fenwick {
	var f Fenwick
	f.data = make([]int, size)
	return &f
}

func (f *Fenwick) Add(pos int, value int) error {
	if pos < 0 || pos >= len(f.data) {
		return errors.New("index is out of range")
	}

	for ; pos < len(f.data); pos = pos | (pos + 1) {
		f.data[pos] += value
	}

	return nil
}

func (f *Fenwick) Sum(begin, end int) int64 {
	endSum := f.prefixSum(end)
	beginSum := f.prefixSum(begin - 1)
	return endSum - beginSum
}

func (f *Fenwick) prefixSum(pos int) int64 {
	var result int64
	if pos >= len(f.data) {
		pos = len(f.data) - 1
	}

	for ; pos >= 0; pos = (pos & (pos + 1)) - 1 {
		result += int64(f.data[pos])
	}

	return result
}

/*
URL:
https://codeforces.com/contest/1430/problem/E
*/

package main

import (
	"bufio"
	"fmt"
	"io"
	"math"
	"os"
	"strconv"
)

func Reverse(A []rune) []rune {
	res := []rune{}

	n := len(A)
	for i := n - 1; i >= 0; i-- {
		res = append(res, A[i])
	}

	return res
}

var (
	n int
	S []rune

	U [30][]int
)

func main() {
	defer stdout.Flush()

	n = readi()
	S = readrs()

	for i := 0; i < n; i++ {
		c := S[i] - 'a'
		U[c] = append(U[c], i)
	}

	f := func(lv, rv T) T {
		return lv + rv
	}
	g := func(to T, from E) T {
		return to + T(from)
	}
	h := func(to, from E) E {
		return to + from
	}
	p := func(e E, length int) E {
		return e * E(length)
	}
	ti := T(0)
	ei := E(0)
	lst := NewLazySegmentTree(n, f, g, h, p, ti, ei)

	ans := 0
	revS := Reverse(S)
	for i := 0; i < n; i++ {
		c := revS[i] - 'a'

		idx := U[c][0]
		U[c] = U[c][1:] // 捨てる

		// plus := ft.RangeSum(0, idx)
		plus := int(lst.Query(idx, idx+1))
		j := idx + plus

		ans += j - i
		// debugf("%d: %d\n", i, j-i)

		// if idx-1 >= 0 {
		// ft.Add(j-1, 1)
		lst.Update(0, idx, E(1))
		// }
	}

	printf("%d\n", ans)
}

// Assumption: T == E
type T int // (T, f): Monoid
type E int // (E, h): Operator Monoid

type LazySegmentTree struct {
	sz   int
	data []T
	lazy []E
	f    func(lv, rv T) T        // T <> T -> T
	g    func(to T, from E) T    // T <> E -> T (assignment operator)
	h    func(to, from E) E      // E <> E -> E (assignment operator)
	p    func(e E, length int) E // E <> N -> E
	ti   T
	ei   E
}

func NewLazySegmentTree(
	n int,
	f func(lv, rv T) T, g func(to T, from E) T,
	h func(to, from E) E, p func(e E, length int) E,
	ti T, ei E,
) *LazySegmentTree {
	lst := new(LazySegmentTree)
	lst.f, lst.g, lst.h, lst.p = f, g, h, p
	lst.ti, lst.ei = ti, ei

	lst.sz = 1
	for lst.sz < n {
		lst.sz *= 2
	}

	lst.data = make([]T, 2*lst.sz-1)
	lst.lazy = make([]E, 2*lst.sz-1)
	for i := 0; i < 2*lst.sz-1; i++ {
		lst.data[i] = lst.ti
		lst.lazy[i] = lst.ei
	}

	return lst
}

func (lst *LazySegmentTree) Set(k int, x T) {
	lst.data[k+(lst.sz-1)] = x
}

func (lst *LazySegmentTree) Build() {
	for i := lst.sz - 2; i >= 0; i-- {
		lst.data[i] = lst.f(lst.data[2*i+1], lst.data[2*i+2])
	}
}

func (lst *LazySegmentTree) propagate(k, length int) {
	if lst.lazy[k] != lst.ei {
		if k < lst.sz-1 {
			lst.lazy[2*k+1] = lst.h(lst.lazy[2*k+1], lst.lazy[k])
			lst.lazy[2*k+2] = lst.h(lst.lazy[2*k+2], lst.lazy[k])
		}
		lst.data[k] = lst.g(lst.data[k], lst.p(lst.lazy[k], length))
		lst.lazy[k] = lst.ei
	}
}

func (lst *LazySegmentTree) Update(a, b int, x E) T {
	return lst.update(a, b, x, 0, 0, lst.sz)
}

func (lst *LazySegmentTree) update(a, b int, x E, k, l, r int) T {
	lst.propagate(k, r-l)

	if r <= a || b <= l {
		return lst.data[k]
	}

	if a <= l && r <= b {
		lst.lazy[k] = lst.h(lst.lazy[k], x)
		lst.propagate(k, r-l)
		return lst.data[k]
	}

	lv := lst.update(a, b, x, 2*k+1, l, (l+r)/2)
	rv := lst.update(a, b, x, 2*k+2, (l+r)/2, r)
	lst.data[k] = lst.f(lv, rv)
	return lst.data[k]
}

func (lst *LazySegmentTree) Query(a, b int) T {
	return lst.query(a, b, 0, 0, lst.sz)
}

func (lst *LazySegmentTree) query(a, b, k, l, r int) T {
	lst.propagate(k, r-l)

	if r <= a || b <= l {
		return lst.ti
	}

	if a <= l && r <= b {
		return lst.data[k]
	}

	lv := lst.query(a, b, 2*k+1, l, (l+r)/2)
	rv := lst.query(a, b, 2*k+2, (l+r)/2, r)
	return lst.f(lv, rv)
}

func (lst *LazySegmentTree) Get(k int) T {
	return lst.Query(k, k+1)
}

/*******************************************************************/

/********** common constants **********/

const (
	MOD = 1000000000 + 7
	// MOD          = 998244353
	ALPH_N  = 26
	INF_I64 = math.MaxInt64
	INF_B60 = 1 << 60
	INF_I32 = math.MaxInt32
	INF_B30 = 1 << 30
	NIL     = -1
	EPS     = 1e-10
)

/********** bufio setting **********/

func init() {
	// bufio.ScanWords <---> bufio.ScanLines
	reads = newReadString(os.Stdin, bufio.ScanWords)
	stdout = bufio.NewWriter(os.Stdout)
}

// mod can calculate a right residual whether value is positive or negative.
func mod(val, m int) int {
	res := val % m
	if res < 0 {
		res += m
	}
	return res
}

// min returns the min integer among input set.
// This function needs at least 1 argument (no argument causes panic).
func min(integers ...int) int {
	m := integers[0]
	for i, integer := range integers {
		if i == 0 {
			continue
		}
		if m > integer {
			m = integer
		}
	}
	return m
}

// max returns the max integer among input set.
// This function needs at least 1 argument (no argument causes panic).
func max(integers ...int) int {
	m := integers[0]
	for i, integer := range integers {
		if i == 0 {
			continue
		}
		if m < integer {
			m = integer
		}
	}
	return m
}

// chmin accepts a pointer of integer and a target value.
// If target value is SMALLER than the first argument,
//	then the first argument will be updated by the second argument.
func chmin(updatedValue *int, target int) bool {
	if *updatedValue > target {
		*updatedValue = target
		return true
	}
	return false
}

// chmax accepts a pointer of integer and a target value.
// If target value is LARGER than the first argument,
//	then the first argument will be updated by the second argument.
func chmax(updatedValue *int, target int) bool {
	if *updatedValue < target {
		*updatedValue = target
		return true
	}
	return false
}

// sum returns multiple integers sum.
func sum(integers ...int) int {
	var s int
	s = 0

	for _, i := range integers {
		s += i
	}

	return s
}

/********** FAU standard libraries **********/

//fmt.Sprintf("%b\n", 255) 	// binary expression

/********** I/O usage **********/

//str := reads()
//i := readi()
//X := readis(n)
//S := readrs()
//a := readf()
//A := readfs(n)

//str := ZeroPaddingRuneSlice(num, 32)
//str := PrintIntsLine(X...)

/*********** Input ***********/

var (
	// reads returns a WORD string.
	reads  func() string
	stdout *bufio.Writer
)

func newReadString(ior io.Reader, sf bufio.SplitFunc) func() string {
	r := bufio.NewScanner(ior)
	r.Buffer(make([]byte, 1024), int(1e+9)) // for Codeforces
	r.Split(sf)

	return func() string {
		if !r.Scan() {
			panic("Scan failed")
		}
		return r.Text()
	}
}

// readi returns an integer.
func readi() int {
	return int(_readInt64())
}
func readi2() (int, int) {
	return int(_readInt64()), int(_readInt64())
}
func readi3() (int, int, int) {
	return int(_readInt64()), int(_readInt64()), int(_readInt64())
}
func readi4() (int, int, int, int) {
	return int(_readInt64()), int(_readInt64()), int(_readInt64()), int(_readInt64())
}

// readll returns as integer as int64.
func readll() int64 {
	return _readInt64()
}
func readll2() (int64, int64) {
	return _readInt64(), _readInt64()
}
func readll3() (int64, int64, int64) {
	return _readInt64(), _readInt64(), _readInt64()
}
func readll4() (int64, int64, int64, int64) {
	return _readInt64(), _readInt64(), _readInt64(), _readInt64()
}

func _readInt64() int64 {
	i, err := strconv.ParseInt(reads(), 0, 64)
	if err != nil {
		panic(err.Error())
	}
	return i
}

// readis returns an integer slice that has n integers.
func readis(n int) []int {
	b := make([]int, n)
	for i := 0; i < n; i++ {
		b[i] = readi()
	}
	return b
}

// readlls returns as int64 slice that has n integers.
func readlls(n int) []int64 {
	b := make([]int64, n)
	for i := 0; i < n; i++ {
		b[i] = readll()
	}
	return b
}

// readf returns an float64.
func readf() float64 {
	return float64(_readFloat64())
}

func _readFloat64() float64 {
	f, err := strconv.ParseFloat(reads(), 64)
	if err != nil {
		panic(err.Error())
	}
	return f
}

// ReadFloatSlice returns an float64 slice that has n float64.
func readfs(n int) []float64 {
	b := make([]float64, n)
	for i := 0; i < n; i++ {
		b[i] = readf()
	}
	return b
}

// readrs returns a rune slice.
func readrs() []rune {
	return []rune(reads())
}

/*********** Output ***********/

// PrintIntsLine returns integers string delimited by a space.
func PrintIntsLine(A ...int) string {
	res := []rune{}

	for i := 0; i < len(A); i++ {
		str := strconv.Itoa(A[i])
		res = append(res, []rune(str)...)

		if i != len(A)-1 {
			res = append(res, ' ')
		}
	}

	return string(res)
}

// PrintIntsLine returns integers string delimited by a space.
func PrintInts64Line(A ...int64) string {
	res := []rune{}

	for i := 0; i < len(A); i++ {
		str := strconv.FormatInt(A[i], 10) // 64bit int version
		res = append(res, []rune(str)...)

		if i != len(A)-1 {
			res = append(res, ' ')
		}
	}

	return string(res)
}

// Printf is function for output strings to buffered os.Stdout.
// You may have to call stdout.Flush() finally.
func printf(format string, a ...interface{}) {
	fmt.Fprintf(stdout, format, a...)
}

/*********** Debugging ***********/

// debugf is wrapper of fmt.Fprintf(os.Stderr, format, a...)
func debugf(format string, a ...interface{}) {
	fmt.Fprintf(os.Stderr, format, a...)
}

// ZeroPaddingRuneSlice returns binary expressions of integer n with zero padding.
// For debugging use.
func ZeroPaddingRuneSlice(n, digitsNum int) []rune {
	sn := fmt.Sprintf("%b", n)

	residualLength := digitsNum - len(sn)
	if residualLength <= 0 {
		return []rune(sn)
	}

	zeros := make([]rune, residualLength)
	for i := 0; i < len(zeros); i++ {
		zeros[i] = '0'
	}

	res := []rune{}
	res = append(res, zeros...)
	res = append(res, []rune(sn)...)

	return res
}

/*
URL:
https://codeforces.com/contest/1430/problem/E
*/

package main

import (
	"bufio"
	"fmt"
	"io"
	"math"
	"os"
	"strconv"
)

func Reverse(A []rune) []rune {
	res := []rune{}

	n := len(A)
	for i := n - 1; i >= 0; i-- {
		res = append(res, A[i])
	}

	return res
}

var (
	n int
	S []rune

	U [30][]int
)

func main() {
	defer stdout.Flush()

	n = readi()
	S = readrs()

	for i := 0; i < n; i++ {
		c := S[i] - 'a'
		U[c] = append(U[c], i)
	}

	f := func(lv, rv T) T {
		return lv + rv
	}
	g := func(to T, from E) T {
		return to + T(from)
	}
	h := func(to, from E) E {
		return to + from
	}
	p := func(e E, length int) E {
		return e * E(length)
	}
	ti := T(0)
	ei := E(0)
	lst := NewLazySegmentTree(n, f, g, h, p, ti, ei)

	ans := 0
	revS := Reverse(S)

	if string(S) == string(revS) {
		printf("0\n")
		return
	}

	for i := 0; i < n; i++ {
		c := revS[i] - 'a'

		idx := U[c][0]
		U[c] = U[c][1:] // 捨てる

		// plus := ft.RangeSum(0, idx)
		plus := int(lst.Query(idx, idx+1))
		j := idx + plus

		ans += j - i
		// debugf("%d: %d\n", i, j-i)

		// if idx-1 >= 0 {
		// ft.Add(j-1, 1)
		lst.Update(0, idx, E(1))
		// }
	}

	printf("%d\n", ans)
}

// Assumption: T == E
type T int // (T, f): Monoid
type E int // (E, h): Operator Monoid

type LazySegmentTree struct {
	sz   int
	data []T
	lazy []E
	f    func(lv, rv T) T        // T <> T -> T
	g    func(to T, from E) T    // T <> E -> T (assignment operator)
	h    func(to, from E) E      // E <> E -> E (assignment operator)
	p    func(e E, length int) E // E <> N -> E
	ti   T
	ei   E
}

func NewLazySegmentTree(
	n int,
	f func(lv, rv T) T, g func(to T, from E) T,
	h func(to, from E) E, p func(e E, length int) E,
	ti T, ei E,
) *LazySegmentTree {
	lst := new(LazySegmentTree)
	lst.f, lst.g, lst.h, lst.p = f, g, h, p
	lst.ti, lst.ei = ti, ei

	lst.sz = 1
	for lst.sz < n {
		lst.sz *= 2
	}

	lst.data = make([]T, 2*lst.sz-1)
	lst.lazy = make([]E, 2*lst.sz-1)
	for i := 0; i < 2*lst.sz-1; i++ {
		lst.data[i] = lst.ti
		lst.lazy[i] = lst.ei
	}

	return lst
}

func (lst *LazySegmentTree) Set(k int, x T) {
	lst.data[k+(lst.sz-1)] = x
}

func (lst *LazySegmentTree) Build() {
	for i := lst.sz - 2; i >= 0; i-- {
		lst.data[i] = lst.f(lst.data[2*i+1], lst.data[2*i+2])
	}
}

func (lst *LazySegmentTree) propagate(k, length int) {
	if lst.lazy[k] != lst.ei {
		if k < lst.sz-1 {
			lst.lazy[2*k+1] = lst.h(lst.lazy[2*k+1], lst.lazy[k])
			lst.lazy[2*k+2] = lst.h(lst.lazy[2*k+2], lst.lazy[k])
		}
		lst.data[k] = lst.g(lst.data[k], lst.p(lst.lazy[k], length))
		lst.lazy[k] = lst.ei
	}
}

func (lst *LazySegmentTree) Update(a, b int, x E) T {
	return lst.update(a, b, x, 0, 0, lst.sz)
}

func (lst *LazySegmentTree) update(a, b int, x E, k, l, r int) T {
	lst.propagate(k, r-l)

	if r <= a || b <= l {
		return lst.data[k]
	}

	if a <= l && r <= b {
		lst.lazy[k] = lst.h(lst.lazy[k], x)
		lst.propagate(k, r-l)
		return lst.data[k]
	}

	lv := lst.update(a, b, x, 2*k+1, l, (l+r)/2)
	rv := lst.update(a, b, x, 2*k+2, (l+r)/2, r)
	lst.data[k] = lst.f(lv, rv)
	return lst.data[k]
}

func (lst *LazySegmentTree) Query(a, b int) T {
	return lst.query(a, b, 0, 0, lst.sz)
}

func (lst *LazySegmentTree) query(a, b, k, l, r int) T {
	lst.propagate(k, r-l)

	if r <= a || b <= l {
		return lst.ti
	}

	if a <= l && r <= b {
		return lst.data[k]
	}

	lv := lst.query(a, b, 2*k+1, l, (l+r)/2)
	rv := lst.query(a, b, 2*k+2, (l+r)/2, r)
	return lst.f(lv, rv)
}

func (lst *LazySegmentTree) Get(k int) T {
	return lst.Query(k, k+1)
}

/*******************************************************************/

/********** common constants **********/

const (
	MOD = 1000000000 + 7
	// MOD          = 998244353
	ALPH_N  = 26
	INF_I64 = math.MaxInt64
	INF_B60 = 1 << 60
	INF_I32 = math.MaxInt32
	INF_B30 = 1 << 30
	NIL     = -1
	EPS     = 1e-10
)

/********** bufio setting **********/

func init() {
	// bufio.ScanWords <---> bufio.ScanLines
	reads = newReadString(os.Stdin, bufio.ScanWords)
	stdout = bufio.NewWriter(os.Stdout)
}

// mod can calculate a right residual whether value is positive or negative.
func mod(val, m int) int {
	res := val % m
	if res < 0 {
		res += m
	}
	return res
}

// min returns the min integer among input set.
// This function needs at least 1 argument (no argument causes panic).
func min(integers ...int) int {
	m := integers[0]
	for i, integer := range integers {
		if i == 0 {
			continue
		}
		if m > integer {
			m = integer
		}
	}
	return m
}

// max returns the max integer among input set.
// This function needs at least 1 argument (no argument causes panic).
func max(integers ...int) int {
	m := integers[0]
	for i, integer := range integers {
		if i == 0 {
			continue
		}
		if m < integer {
			m = integer
		}
	}
	return m
}

// chmin accepts a pointer of integer and a target value.
// If target value is SMALLER than the first argument,
//	then the first argument will be updated by the second argument.
func chmin(updatedValue *int, target int) bool {
	if *updatedValue > target {
		*updatedValue = target
		return true
	}
	return false
}

// chmax accepts a pointer of integer and a target value.
// If target value is LARGER than the first argument,
//	then the first argument will be updated by the second argument.
func chmax(updatedValue *int, target int) bool {
	if *updatedValue < target {
		*updatedValue = target
		return true
	}
	return false
}

// sum returns multiple integers sum.
func sum(integers ...int) int {
	var s int
	s = 0

	for _, i := range integers {
		s += i
	}

	return s
}

/********** FAU standard libraries **********/

//fmt.Sprintf("%b\n", 255) 	// binary expression

/********** I/O usage **********/

//str := reads()
//i := readi()
//X := readis(n)
//S := readrs()
//a := readf()
//A := readfs(n)

//str := ZeroPaddingRuneSlice(num, 32)
//str := PrintIntsLine(X...)

/*********** Input ***********/

var (
	// reads returns a WORD string.
	reads  func() string
	stdout *bufio.Writer
)

func newReadString(ior io.Reader, sf bufio.SplitFunc) func() string {
	r := bufio.NewScanner(ior)
	r.Buffer(make([]byte, 1024), int(1e+9)) // for Codeforces
	r.Split(sf)

	return func() string {
		if !r.Scan() {
			panic("Scan failed")
		}
		return r.Text()
	}
}

// readi returns an integer.
func readi() int {
	return int(_readInt64())
}
func readi2() (int, int) {
	return int(_readInt64()), int(_readInt64())
}
func readi3() (int, int, int) {
	return int(_readInt64()), int(_readInt64()), int(_readInt64())
}
func readi4() (int, int, int, int) {
	return int(_readInt64()), int(_readInt64()), int(_readInt64()), int(_readInt64())
}

// readll returns as integer as int64.
func readll() int64 {
	return _readInt64()
}
func readll2() (int64, int64) {
	return _readInt64(), _readInt64()
}
func readll3() (int64, int64, int64) {
	return _readInt64(), _readInt64(), _readInt64()
}
func readll4() (int64, int64, int64, int64) {
	return _readInt64(), _readInt64(), _readInt64(), _readInt64()
}

func _readInt64() int64 {
	i, err := strconv.ParseInt(reads(), 0, 64)
	if err != nil {
		panic(err.Error())
	}
	return i
}

// readis returns an integer slice that has n integers.
func readis(n int) []int {
	b := make([]int, n)
	for i := 0; i < n; i++ {
		b[i] = readi()
	}
	return b
}

// readlls returns as int64 slice that has n integers.
func readlls(n int) []int64 {
	b := make([]int64, n)
	for i := 0; i < n; i++ {
		b[i] = readll()
	}
	return b
}

// readf returns an float64.
func readf() float64 {
	return float64(_readFloat64())
}

func _readFloat64() float64 {
	f, err := strconv.ParseFloat(reads(), 64)
	if err != nil {
		panic(err.Error())
	}
	return f
}

// ReadFloatSlice returns an float64 slice that has n float64.
func readfs(n int) []float64 {
	b := make([]float64, n)
	for i := 0; i < n; i++ {
		b[i] = readf()
	}
	return b
}

// readrs returns a rune slice.
func readrs() []rune {
	return []rune(reads())
}

/*********** Output ***********/

// PrintIntsLine returns integers string delimited by a space.
func PrintIntsLine(A ...int) string {
	res := []rune{}

	for i := 0; i < len(A); i++ {
		str := strconv.Itoa(A[i])
		res = append(res, []rune(str)...)

		if i != len(A)-1 {
			res = append(res, ' ')
		}
	}

	return string(res)
}

// PrintIntsLine returns integers string delimited by a space.
func PrintInts64Line(A ...int64) string {
	res := []rune{}

	for i := 0; i < len(A); i++ {
		str := strconv.FormatInt(A[i], 10) // 64bit int version
		res = append(res, []rune(str)...)

		if i != len(A)-1 {
			res = append(res, ' ')
		}
	}

	return string(res)
}

// Printf is function for output strings to buffered os.Stdout.
// You may have to call stdout.Flush() finally.
func printf(format string, a ...interface{}) {
	fmt.Fprintf(stdout, format, a...)
}

/*********** Debugging ***********/

// debugf is wrapper of fmt.Fprintf(os.Stderr, format, a...)
func debugf(format string, a ...interface{}) {
	fmt.Fprintf(os.Stderr, format, a...)
}

// ZeroPaddingRuneSlice returns binary expressions of integer n with zero padding.
// For debugging use.
func ZeroPaddingRuneSlice(n, digitsNum int) []rune {
	sn := fmt.Sprintf("%b", n)

	residualLength := digitsNum - len(sn)
	if residualLength <= 0 {
		return []rune(sn)
	}

	zeros := make([]rune, residualLength)
	for i := 0; i < len(zeros); i++ {
		zeros[i] = '0'
	}

	res := []rune{}
	res = append(res, zeros...)
	res = append(res, []rune(sn)...)

	return res
}

/*
URL:
https://codeforces.com/contest/1430/problem/E
*/

package main

import (
	"bufio"
	"fmt"
	"io"
	"math"
	"os"
	"strconv"
)

func Reverse(A []rune) []rune {
	res := []rune{}

	n := len(A)
	for i := n - 1; i >= 0; i-- {
		res = append(res, A[i])
	}

	return res
}

var (
	n int
	S []rune

	U [30][]int
)

func main() {
	defer stdout.Flush()

	n = readi()
	S = readrs()

	for i := 0; i < n; i++ {
		c := S[i] - 'a'
		U[c] = append(U[c], i)
	}

	f := func(lv, rv T) T {
		return lv + rv
	}
	g := func(to T, from E) T {
		return to + T(from)
	}
	h := func(to, from E) E {
		return to + from
	}
	p := func(e E, length int) E {
		return e * E(length)
	}
	ti := T(0)
	ei := E(0)
	lst := NewLazySegmentTree(n+100, f, g, h, p, ti, ei)

	ans := 0
	revS := Reverse(S)
	for i := 0; i < n; i++ {
		c := revS[i] - 'a'

		idx := U[c][0]
		U[c] = U[c][1:] // 捨てる

		// plus := ft.RangeSum(0, idx)
		plus := int(lst.Query(idx, idx+1))
		j := idx + plus

		ans += j - i
		// debugf("%d: %d\n", i, j-i)

		// if idx-1 >= 0 {
		// ft.Add(j-1, 1)
		lst.Update(0, idx, E(1))
		// }
	}

	printf("%d\n", ans)
}

// Assumption: T == E
type T int // (T, f): Monoid
type E int // (E, h): Operator Monoid

type LazySegmentTree struct {
	sz   int
	data []T
	lazy []E
	f    func(lv, rv T) T        // T <> T -> T
	g    func(to T, from E) T    // T <> E -> T (assignment operator)
	h    func(to, from E) E      // E <> E -> E (assignment operator)
	p    func(e E, length int) E // E <> N -> E
	ti   T
	ei   E
}

func NewLazySegmentTree(
	n int,
	f func(lv, rv T) T, g func(to T, from E) T,
	h func(to, from E) E, p func(e E, length int) E,
	ti T, ei E,
) *LazySegmentTree {
	lst := new(LazySegmentTree)
	lst.f, lst.g, lst.h, lst.p = f, g, h, p
	lst.ti, lst.ei = ti, ei

	lst.sz = 1
	for lst.sz < n {
		lst.sz *= 2
	}

	lst.data = make([]T, 2*lst.sz-1)
	lst.lazy = make([]E, 2*lst.sz-1)
	for i := 0; i < 2*lst.sz-1; i++ {
		lst.data[i] = lst.ti
		lst.lazy[i] = lst.ei
	}

	return lst
}

func (lst *LazySegmentTree) Set(k int, x T) {
	lst.data[k+(lst.sz-1)] = x
}

func (lst *LazySegmentTree) Build() {
	for i := lst.sz - 2; i >= 0; i-- {
		lst.data[i] = lst.f(lst.data[2*i+1], lst.data[2*i+2])
	}
}

func (lst *LazySegmentTree) propagate(k, length int) {
	if lst.lazy[k] != lst.ei {
		if k < lst.sz-1 {
			lst.lazy[2*k+1] = lst.h(lst.lazy[2*k+1], lst.lazy[k])
			lst.lazy[2*k+2] = lst.h(lst.lazy[2*k+2], lst.lazy[k])
		}
		lst.data[k] = lst.g(lst.data[k], lst.p(lst.lazy[k], length))
		lst.lazy[k] = lst.ei
	}
}

func (lst *LazySegmentTree) Update(a, b int, x E) T {
	return lst.update(a, b, x, 0, 0, lst.sz)
}

func (lst *LazySegmentTree) update(a, b int, x E, k, l, r int) T {
	lst.propagate(k, r-l)

	if r <= a || b <= l {
		return lst.data[k]
	}

	if a <= l && r <= b {
		lst.lazy[k] = lst.h(lst.lazy[k], x)
		lst.propagate(k, r-l)
		return lst.data[k]
	}

	lv := lst.update(a, b, x, 2*k+1, l, (l+r)/2)
	rv := lst.update(a, b, x, 2*k+2, (l+r)/2, r)
	lst.data[k] = lst.f(lv, rv)
	return lst.data[k]
}

func (lst *LazySegmentTree) Query(a, b int) T {
	return lst.query(a, b, 0, 0, lst.sz)
}

func (lst *LazySegmentTree) query(a, b, k, l, r int) T {
	lst.propagate(k, r-l)

	if r <= a || b <= l {
		return lst.ti
	}

	if a <= l && r <= b {
		return lst.data[k]
	}

	lv := lst.query(a, b, 2*k+1, l, (l+r)/2)
	rv := lst.query(a, b, 2*k+2, (l+r)/2, r)
	return lst.f(lv, rv)
}

func (lst *LazySegmentTree) Get(k int) T {
	return lst.Query(k, k+1)
}

/*******************************************************************/

/********** common constants **********/

const (
	MOD = 1000000000 + 7
	// MOD          = 998244353
	ALPH_N  = 26
	INF_I64 = math.MaxInt64
	INF_B60 = 1 << 60
	INF_I32 = math.MaxInt32
	INF_B30 = 1 << 30
	NIL     = -1
	EPS     = 1e-10
)

/********** bufio setting **********/

func init() {
	// bufio.ScanWords <---> bufio.ScanLines
	reads = newReadString(os.Stdin, bufio.ScanWords)
	stdout = bufio.NewWriter(os.Stdout)
}

// mod can calculate a right residual whether value is positive or negative.
func mod(val, m int) int {
	res := val % m
	if res < 0 {
		res += m
	}
	return res
}

// min returns the min integer among input set.
// This function needs at least 1 argument (no argument causes panic).
func min(integers ...int) int {
	m := integers[0]
	for i, integer := range integers {
		if i == 0 {
			continue
		}
		if m > integer {
			m = integer
		}
	}
	return m
}

// max returns the max integer among input set.
// This function needs at least 1 argument (no argument causes panic).
func max(integers ...int) int {
	m := integers[0]
	for i, integer := range integers {
		if i == 0 {
			continue
		}
		if m < integer {
			m = integer
		}
	}
	return m
}

// chmin accepts a pointer of integer and a target value.
// If target value is SMALLER than the first argument,
//	then the first argument will be updated by the second argument.
func chmin(updatedValue *int, target int) bool {
	if *updatedValue > target {
		*updatedValue = target
		return true
	}
	return false
}

// chmax accepts a pointer of integer and a target value.
// If target value is LARGER than the first argument,
//	then the first argument will be updated by the second argument.
func chmax(updatedValue *int, target int) bool {
	if *updatedValue < target {
		*updatedValue = target
		return true
	}
	return false
}

// sum returns multiple integers sum.
func sum(integers ...int) int {
	var s int
	s = 0

	for _, i := range integers {
		s += i
	}

	return s
}

/********** FAU standard libraries **********/

//fmt.Sprintf("%b\n", 255) 	// binary expression

/********** I/O usage **********/

//str := reads()
//i := readi()
//X := readis(n)
//S := readrs()
//a := readf()
//A := readfs(n)

//str := ZeroPaddingRuneSlice(num, 32)
//str := PrintIntsLine(X...)

/*********** Input ***********/

var (
	// reads returns a WORD string.
	reads  func() string
	stdout *bufio.Writer
)

func newReadString(ior io.Reader, sf bufio.SplitFunc) func() string {
	r := bufio.NewScanner(ior)
	r.Buffer(make([]byte, 1024), int(1e+9)) // for Codeforces
	r.Split(sf)

	return func() string {
		if !r.Scan() {
			panic("Scan failed")
		}
		return r.Text()
	}
}

// readi returns an integer.
func readi() int {
	return int(_readInt64())
}
func readi2() (int, int) {
	return int(_readInt64()), int(_readInt64())
}
func readi3() (int, int, int) {
	return int(_readInt64()), int(_readInt64()), int(_readInt64())
}
func readi4() (int, int, int, int) {
	return int(_readInt64()), int(_readInt64()), int(_readInt64()), int(_readInt64())
}

// readll returns as integer as int64.
func readll() int64 {
	return _readInt64()
}
func readll2() (int64, int64) {
	return _readInt64(), _readInt64()
}
func readll3() (int64, int64, int64) {
	return _readInt64(), _readInt64(), _readInt64()
}
func readll4() (int64, int64, int64, int64) {
	return _readInt64(), _readInt64(), _readInt64(), _readInt64()
}

func _readInt64() int64 {
	i, err := strconv.ParseInt(reads(), 0, 64)
	if err != nil {
		panic(err.Error())
	}
	return i
}

// readis returns an integer slice that has n integers.
func readis(n int) []int {
	b := make([]int, n)
	for i := 0; i < n; i++ {
		b[i] = readi()
	}
	return b
}

// readlls returns as int64 slice that has n integers.
func readlls(n int) []int64 {
	b := make([]int64, n)
	for i := 0; i < n; i++ {
		b[i] = readll()
	}
	return b
}

// readf returns an float64.
func readf() float64 {
	return float64(_readFloat64())
}

func _readFloat64() float64 {
	f, err := strconv.ParseFloat(reads(), 64)
	if err != nil {
		panic(err.Error())
	}
	return f
}

// ReadFloatSlice returns an float64 slice that has n float64.
func readfs(n int) []float64 {
	b := make([]float64, n)
	for i := 0; i < n; i++ {
		b[i] = readf()
	}
	return b
}

// readrs returns a rune slice.
func readrs() []rune {
	return []rune(reads())
}

/*********** Output ***********/

// PrintIntsLine returns integers string delimited by a space.
func PrintIntsLine(A ...int) string {
	res := []rune{}

	for i := 0; i < len(A); i++ {
		str := strconv.Itoa(A[i])
		res = append(res, []rune(str)...)

		if i != len(A)-1 {
			res = append(res, ' ')
		}
	}

	return string(res)
}

// PrintIntsLine returns integers string delimited by a space.
func PrintInts64Line(A ...int64) string {
	res := []rune{}

	for i := 0; i < len(A); i++ {
		str := strconv.FormatInt(A[i], 10) // 64bit int version
		res = append(res, []rune(str)...)

		if i != len(A)-1 {
			res = append(res, ' ')
		}
	}

	return string(res)
}

// Printf is function for output strings to buffered os.Stdout.
// You may have to call stdout.Flush() finally.
func printf(format string, a ...interface{}) {
	fmt.Fprintf(stdout, format, a...)
}

/*********** Debugging ***********/

// debugf is wrapper of fmt.Fprintf(os.Stderr, format, a...)
func debugf(format string, a ...interface{}) {
	fmt.Fprintf(os.Stderr, format, a...)
}

// ZeroPaddingRuneSlice returns binary expressions of integer n with zero padding.
// For debugging use.
func ZeroPaddingRuneSlice(n, digitsNum int) []rune {
	sn := fmt.Sprintf("%b", n)

	residualLength := digitsNum - len(sn)
	if residualLength <= 0 {
		return []rune(sn)
	}

	zeros := make([]rune, residualLength)
	for i := 0; i < len(zeros); i++ {
		zeros[i] = '0'
	}

	res := []rune{}
	res = append(res, zeros...)
	res = append(res, []rune(sn)...)

	return res
}

package main

import (
	"bufio"
	"errors"
	"fmt"
	"os"
)

var reader = bufio.NewReader(os.Stdin)

func main() {
	var n int
	fmt.Fscan(reader, &n)

	var s string
	fmt.Fscan(reader, &s)

	runeMap := [26][]int{}
	for i := n - 1; i >= 0; i-- {
		r := s[i] - 'a'
		runeMap[r] = append(runeMap[r], n-i-1)
	}

	pos := []int{}
	for _, r := range s {
		v := runeMap[r-'a'][0]
		runeMap[r-'a'] = runeMap[r-'a'][1:]
		pos = append(pos, v)
	}

	swaps := 0
	f := New(n)
	for i := n - 1; i >= 0; i-- {
		swaps += f.Sum(0, pos[i])
		f.Add(pos[i], 1)
	}

	fmt.Println(swaps)
}

type Fenwick struct {
	data []int
}

func New(size int) *Fenwick {
	var f Fenwick
	f.data = make([]int, size)
	return &f
}

func (f *Fenwick) Add(pos int, value int) error {
	if pos < 0 || pos >= len(f.data) {
		return errors.New("index is out of range")
	}

	for ; pos < len(f.data); pos = pos | (pos + 1) {
		f.data[pos] += value
	}

	return nil
}

func (f *Fenwick) Sum(begin, end int) int {
	endSum := f.prefixSum(end)
	beginSum := f.prefixSum(begin - 1)
	return endSum - beginSum
}

func (f *Fenwick) prefixSum(pos int) int {
	var result int
	if pos >= len(f.data) {
		pos = len(f.data) - 1
	}

	for ; pos >= 0; pos = (pos & (pos + 1)) - 1 {
		result += f.data[pos]
	}

	return result
}


Shuseki Kingdom is the world's leading nation for innovation and technology. There are n cities in the kingdom, numbered from 1 to n.Thanks to Mr. Kitayuta's research, it has finally become possible to construct teleportation pipes between two cities. A teleportation pipe will connect two cities unidirectionally, that is, a teleportation pipe from city x to city y cannot be used to travel from city y to city x. The transportation within each city is extremely developed, therefore if a pipe from city x to city y and a pipe from city y to city z are both constructed, people will be able to travel from city x to city z instantly.Mr. Kitayuta is also involved in national politics. He considers that the transportation between the m pairs of city (ai, bi) (1 ≤ i ≤ m) is important. He is planning to construct teleportation pipes so that for each important pair (ai, bi), it will be possible to travel from city ai to city bi by using one or more teleportation pipes (but not necessarily from city bi to city ai). Find the minimum number of teleportation pipes that need to be constructed. So far, no teleportation pipe has been constructed, and there is no other effective transportation between cities.

The first line contains two space-separated integers n and m (2 ≤ n ≤ 105, 1 ≤ m ≤ 105), denoting the number of the cities in Shuseki Kingdom and the number of the important pairs, respectively. The following m lines describe the important pairs. The i-th of them (1 ≤ i ≤ m) contains two space-separated integers ai and bi (1 ≤ ai, bi ≤ n, ai ≠ bi), denoting that it must be possible to travel from city ai to city bi by using one or more teleportation pipes (but not necessarily from city bi to city ai). It is guaranteed that all pairs (ai, bi) are distinct.

Print the minimum required number of teleportation pipes to fulfill Mr. Kitayuta's purpose.

NoteFor the first sample, one of the optimal ways to construct pipes is shown in the image below:   For the second sample, one of the optimal ways is shown below:

package main

import (
	"bufio"
	"fmt"
	"os"
	"strconv"
)

var sc = bufio.NewScanner(os.Stdin)

func next() string {
	sc.Split(bufio.ScanWords)
	if !sc.Scan() {
		panic("could not scan a word from the reader")
	}
	return sc.Text()
}

func nextInt() int {
	i, e := strconv.Atoi(next())
	if e != nil {
		panic(e)
	}
	return i
}

func nextLong() int64 {
	i, e := strconv.ParseInt(next(), 10, 64)
	if e != nil {
		panic(e)
	}
	return i
}

func nextLine() string {
	sc.Split(bufio.ScanLines)
	if !sc.Scan() {
		panic("could not scan a line from the reader")
	}
	return sc.Text()
}

type graph struct {
	V       int     // The number of vetices
	E       [][]int // Adjacency list expression of the graph
	R       [][]int // Reversed E
	vs      []int   // Post order
	visited []bool  // True if the vertex is visited during DFS
	sccID   []int   // Topological order of the vertex v
	sccSize []int   // The size of SCC indexed by sccID
}

func newGraph(size int) *graph {
	g := &graph{
		V:       size,
		E:       make([][]int, size),
		R:       make([][]int, size),
		vs:      make([]int, 0, size),
		visited: make([]bool, size),
		sccID:   make([]int, size),
		sccSize: make([]int, size),
	}
	return g
}

func (g *graph) addEdge(from, to int) {
	g.E[from] = append(g.E[from], to)
	g.R[to] = append(g.R[to], from)
}

func (g *graph) dfs(v int) {
	g.visited[v] = true
	for i, n := 0, len(g.E[v]); i < n; i++ {
		if !g.visited[g.E[v][i]] {
			g.dfs(g.E[v][i])
		}
	}
	g.vs = append(g.vs, v)
}

func (g *graph) rdfs(v, k int) {
	g.visited[v] = true
	g.sccID[v] = k
	g.sccSize[k]++
	for i, n := 0, len(g.R[v]); i < n; i++ {
		if !g.visited[g.R[v][i]] {
			g.rdfs(g.R[v][i], k)
		}
	}
}

func (g *graph) scc() (k int) {
	g.visited = make([]bool, g.V)
	g.vs = g.vs[:0]
	for i := 0; i < g.V; i++ {
		if !g.visited[i] {
			g.dfs(i)
		}
	}
	g.visited = make([]bool, g.V)
	for i := len(g.vs) - 1; i >= 0; i-- {
		if !g.visited[g.vs[i]] {
			g.rdfs(g.vs[i], k)
			k++
		}
	}
	return k
}

func max(x, y int) int {
	if y > x {
		return y
	}
	return x
}

type unionFind struct {
	id []int
	sz []int
}

func newUnionFind(size int) *unionFind {
	uf := &unionFind{
		id: make([]int, size),
		sz: make([]int, size),
	}
	for i := 0; i < size; i++ {
		uf.id[i] = i
		uf.sz[i] = 1
	}
	return uf
}

func (uf *unionFind) root(x int) int {
	if uf.id[x] == x {
		return x
	}
	uf.id[x] = uf.root(uf.id[x])
	return uf.id[x]
}

func (uf *unionFind) find(p, q int) bool {
	return uf.root(p) == uf.root(q)
}

func (uf *unionFind) union(p, q int) {
	i, j := uf.root(p), uf.root(q)
	if uf.sz[i] < uf.sz[j] {
		uf.id[i] = j
		uf.sz[j] += uf.sz[i]
	} else {
		uf.id[j] = i
		uf.sz[i] += uf.sz[j]
	}
}

func (g *graph) dfs2(v int) (z int) {
	g.visited[v] = true
	z = g.sccSize[g.sccID[v]]
	for i, n := 0, len(g.E[v]); i < n; i++ {
		if !g.visited[g.E[v][i]] {
			z = max(z, g.dfs2(g.E[v][i]))
		}
	}
	for i, n := 0, len(g.R[v]); i < n; i++ {
		if !g.visited[g.R[v][i]] {
			z = max(z, g.dfs2(g.R[v][i]))
		}
	}
	return
}

func main() {
	n, m := nextInt(), nextInt()
	g := newGraph(n)
	uf := newUnionFind(n)
	for i := 0; i < m; i++ {
		a, b := nextInt()-1, nextInt()-1
		g.addEdge(a, b)
		uf.union(a, b)
	}
	g.scc()
	for i := 0; i < n; i++ {
		uf.root(i)
	}
	sccSize := make([]int, n)
	for i := 0; i < n; i++ {
		sccSize[uf.id[i]] = max(sccSize[uf.id[i]], g.sccSize[g.sccID[i]])
	}
	res := n
	for i := 0; i < n; i++ {
		if sccSize[i] == 1 {
			res--
		}
	}
	fmt.Println(res)
}

package main

import (
	"bufio"
	"fmt"
	"os"
	"strconv"
)

var sc = bufio.NewScanner(os.Stdin)

func next() string {
	sc.Split(bufio.ScanWords)
	if !sc.Scan() {
		panic("could not scan a word from the reader")
	}
	return sc.Text()
}

func nextInt() int {
	i, e := strconv.Atoi(next())
	if e != nil {
		panic(e)
	}
	return i
}

func nextLong() int64 {
	i, e := strconv.ParseInt(next(), 10, 64)
	if e != nil {
		panic(e)
	}
	return i
}

func nextLine() string {
	sc.Split(bufio.ScanLines)
	if !sc.Scan() {
		panic("could not scan a line from the reader")
	}
	return sc.Text()
}

type graph struct {
	V       int     // The number of vetices
	E       [][]int // Adjacency list expression of the graph
	R       [][]int // Reversed E
	vs      []int   // Post order
	visited []bool  // True if the vertex is visited during DFS
	sccID   []int   // Topological order of the vertex v
	sccSize []int   // The size of SCC indexed by sccID
}

func newGraph(size int) *graph {
	g := &graph{
		V:       size,
		E:       make([][]int, size),
		R:       make([][]int, size),
		vs:      make([]int, 0, size),
		visited: make([]bool, size),
		sccID:   make([]int, size),
		sccSize: make([]int, size),
	}
	return g
}

func (g *graph) addEdge(from, to int) {
	g.E[from] = append(g.E[from], to)
	g.R[to] = append(g.R[to], from)
}

func (g *graph) dfs(v int) {
	g.visited[v] = true
	for i, n := 0, len(g.E[v]); i < n; i++ {
		if !g.visited[g.E[v][i]] {
			g.dfs(g.E[v][i])
		}
	}
	g.vs = append(g.vs, v)
}

func (g *graph) rdfs(v, k int) {
	g.visited[v] = true
	g.sccID[v] = k
	g.sccSize[k]++
	for i, n := 0, len(g.R[v]); i < n; i++ {
		if !g.visited[g.R[v][i]] {
			g.rdfs(g.R[v][i], k)
		}
	}
}

func (g *graph) scc() (k int) {
	g.visited = make([]bool, g.V)
	g.vs = g.vs[:0]
	for i := 0; i < g.V; i++ {
		if !g.visited[i] {
			g.dfs(i)
		}
	}
	g.visited = make([]bool, g.V)
	for i := len(g.vs) - 1; i >= 0; i-- {
		if !g.visited[g.vs[i]] {
			g.rdfs(g.vs[i], k)
			k++
		}
	}
	return k
}

func max(x, y int) int {
	if y > x {
		return y
	}
	return x
}

type unionFind struct{ id, sz []int }

func newUnionFind(size int) *unionFind {
	uf := &unionFind{id: make([]int, size), sz: make([]int, size)}
	for i := 0; i < size; i++ {
		uf.id[i], uf.sz[i] = i, 1
	}
	return uf
}

func (uf *unionFind) root(x int) int {
	if uf.id[x] != x {
		uf.id[x] = uf.root(uf.id[x])
	}
	return uf.id[x]
}

func (uf *unionFind) find(p, q int) bool {
	return uf.root(p) == uf.root(q)
}

func (uf *unionFind) union(p, q int) {
	i, j := uf.root(p), uf.root(q)
	if uf.sz[i] < uf.sz[j] {
		uf.id[i] = j
		uf.sz[j] += uf.sz[i]
	} else {
		uf.id[j] = i
		uf.sz[i] += uf.sz[j]
	}
}

func (g *graph) dfs2(v int) (z int) {
	g.visited[v] = true
	z = g.sccSize[g.sccID[v]]
	for i, n := 0, len(g.E[v]); i < n; i++ {
		if !g.visited[g.E[v][i]] {
			z = max(z, g.dfs2(g.E[v][i]))
		}
	}
	for i, n := 0, len(g.R[v]); i < n; i++ {
		if !g.visited[g.R[v][i]] {
			z = max(z, g.dfs2(g.R[v][i]))
		}
	}
	return
}

func main() {
	n, m := nextInt(), nextInt()
	g := newGraph(n)
	uf := newUnionFind(n)
	for i := 0; i < m; i++ {
		a, b := nextInt()-1, nextInt()-1
		g.addEdge(a, b)
		uf.union(a, b)
	}
	g.scc()
	for i := 0; i < n; i++ {
		uf.root(i)
	}
	sccSize := make([]int, n)
	for i := 0; i < n; i++ {
		sccSize[uf.id[i]] = max(sccSize[uf.id[i]], g.sccSize[g.sccID[i]])
	}
	res := n
	for i := 0; i < n; i++ {
		if sccSize[i] == 1 {
			res--
		}
	}
	fmt.Println(res)
}

package main

import (
	"bufio"
	"fmt"
	"os"
	"strconv"
)

var sc = bufio.NewScanner(os.Stdin)

func next() string {
	sc.Split(bufio.ScanWords)
	if !sc.Scan() {
		panic("could not scan a word from the reader")
	}
	return sc.Text()
}

func nextInt() int {
	i, e := strconv.Atoi(next())
	if e != nil {
		panic(e)
	}
	return i
}

func nextLong() int64 {
	i, e := strconv.ParseInt(next(), 10, 64)
	if e != nil {
		panic(e)
	}
	return i
}

func nextLine() string {
	sc.Split(bufio.ScanLines)
	if !sc.Scan() {
		panic("could not scan a line from the reader")
	}
	return sc.Text()
}

type graph struct {
	V       int     // The number of vetices
	E       [][]int // Adjacency list expression of the graph
	R       [][]int // Reversed E
	vs      []int   // Post order
	visited []bool  // True if the vertex is visited during DFS
	sccID   []int   // Topological order of the vertex v
	sccSize []int   // The size of SCC indexed by sccID
}

func newGraph(size int) *graph {
	g := &graph{
		V:       size,
		E:       make([][]int, size),
		R:       make([][]int, size),
		vs:      make([]int, 0, size),
		visited: make([]bool, size),
		sccID:   make([]int, size),
		sccSize: make([]int, size),
	}
	return g
}

func (g *graph) addEdge(from, to int) {
	g.E[from] = append(g.E[from], to)
	g.R[to] = append(g.R[to], from)
}

func (g *graph) dfs(v int) {
	g.visited[v] = true
	for i, n := 0, len(g.E[v]); i < n; i++ {
		if !g.visited[g.E[v][i]] {
			g.dfs(g.E[v][i])
		}
	}
	g.vs = append(g.vs, v)
}

func (g *graph) rdfs(v, k int) {
	g.visited[v] = true
	g.sccID[v] = k
	g.sccSize[k]++
	for i, n := 0, len(g.R[v]); i < n; i++ {
		if !g.visited[g.R[v][i]] {
			g.rdfs(g.R[v][i], k)
		}
	}
}

func (g *graph) scc() (k int) {
	g.visited = make([]bool, g.V)
	g.vs = g.vs[:0]
	for i := 0; i < g.V; i++ {
		if !g.visited[i] {
			g.dfs(i)
		}
	}
	g.visited = make([]bool, g.V)
	for i := len(g.vs) - 1; i >= 0; i-- {
		if !g.visited[g.vs[i]] {
			g.rdfs(g.vs[i], k)
			k++
		}
	}
	return k
}

func max(x, y int) int {
	if y > x {
		return y
	}
	return x
}

func (g *graph) dfs2(v int) (z int) {
	g.visited[v] = true
	z = g.sccSize[g.sccID[v]]
	for i, n := 0, len(g.E[v]); i < n; i++ {
		if !g.visited[g.E[v][i]] {
			z = max(z, g.dfs2(g.E[v][i]))
		}
	}
	for i, n := 0, len(g.R[v]); i < n; i++ {
		if !g.visited[g.R[v][i]] {
			z = max(z, g.dfs2(g.R[v][i]))
		}
	}
	return
}

func main() {
	n, m := nextInt(), nextInt()
	g := newGraph(n)
	for i := 0; i < m; i++ {
		a, b := nextInt()-1, nextInt()-1
		g.addEdge(a, b)
	}
	g.scc()
	g.visited = make([]bool, g.V)
	res := n
	for i := 0; i < n; i++ {
		if !g.visited[i] {
			if g.dfs2(i) < 2 {
				res--
			}
		}
	}
	fmt.Println(res)
}

package main

import (
	"bufio"
	"fmt"
	"os"
	"strconv"
)

var sc = bufio.NewScanner(os.Stdin)

func next() string {
	sc.Split(bufio.ScanWords)
	if !sc.Scan() {
		panic("could not scan a word from the reader")
	}
	return sc.Text()
}

func nextInt() int {
	i, e := strconv.Atoi(next())
	if e != nil {
		panic(e)
	}
	return i
}

func nextLong() int64 {
	i, e := strconv.ParseInt(next(), 10, 64)
	if e != nil {
		panic(e)
	}
	return i
}

func nextLine() string {
	sc.Split(bufio.ScanLines)
	if !sc.Scan() {
		panic("could not scan a line from the reader")
	}
	return sc.Text()
}

type graph struct {
	V       int     // The number of vetices
	E       [][]int // Adjacency list expression of the graph
	R       [][]int // Reversed E
	vs      []int   // Post order
	visited []bool  // True if the vertex is visited during DFS
	sccID   []int   // Topological order of the vertex v
	sccSize []int   // The size of SCC indexed by sccID
}

func newGraph(size int) *graph {
	g := &graph{
		V:       size,
		E:       make([][]int, size),
		R:       make([][]int, size),
		vs:      make([]int, 0, size),
		visited: make([]bool, size),
		sccID:   make([]int, size),
		sccSize: make([]int, size),
	}
	return g
}

func (g *graph) addEdge(from, to int) {
	g.E[from] = append(g.E[from], to)
	g.R[to] = append(g.R[to], from)
}

func (g *graph) dfs(v int) {
	g.visited[v] = true
	for i, n := 0, len(g.E[v]); i < n; i++ {
		if !g.visited[g.E[v][i]] {
			g.dfs(g.E[v][i])
		}
	}
	g.vs = append(g.vs, v)
}

func (g *graph) rdfs(v, k int) {
	g.visited[v] = true
	g.sccID[v] = k
	g.sccSize[k]++
	for i, n := 0, len(g.R[v]); i < n; i++ {
		if !g.visited[g.R[v][i]] {
			g.rdfs(g.R[v][i], k)
		}
	}
}

func (g *graph) scc() (k int) {
	g.visited = make([]bool, g.V)
	g.vs = g.vs[:0]
	for i := 0; i < g.V; i++ {
		if !g.visited[i] {
			g.dfs(i)
		}
	}
	g.visited = make([]bool, g.V)
	for i := len(g.vs) - 1; i >= 0; i-- {
		if !g.visited[g.vs[i]] {
			g.rdfs(g.vs[i], k)
			k++
		}
	}
	return k
}

func max(x, y int) int {
	if y > x {
		return y
	}
	return x
}

type unionFind struct {
	id []int
	sz []int
}

func newUnionFind(size int) *unionFind {
	uf := &unionFind{
		id: make([]int, size),
		sz: make([]int, size),
	}
	for i := 0; i < size; i++ {
		uf.id[i] = i
		uf.sz[i] = 1
	}
	return uf
}

func (uf *unionFind) root(i int) int {
	for i != uf.id[i] {
		uf.id[i] = uf.id[uf.id[i]]
		i = uf.id[i]
	}
	return i
}

func (uf *unionFind) find(p, q int) bool {
	return uf.root(p) == uf.root(q)
}

func (uf *unionFind) union(p, q int) {
	i, j := uf.root(p), uf.root(q)
	if uf.sz[i] < uf.sz[j] {
		uf.id[i] = j
		uf.sz[j] += uf.sz[i]
	} else {
		uf.id[j] = i
		uf.sz[i] += uf.sz[j]
	}
}

func (g *graph) dfs2(v int) (z int) {
	g.visited[v] = true
	z = g.sccSize[g.sccID[v]]
	for i, n := 0, len(g.E[v]); i < n; i++ {
		if !g.visited[g.E[v][i]] {
			z = max(z, g.dfs2(g.E[v][i]))
		}
	}
	for i, n := 0, len(g.R[v]); i < n; i++ {
		if !g.visited[g.R[v][i]] {
			z = max(z, g.dfs2(g.R[v][i]))
		}
	}
	return
}

func main() {
	n, m := nextInt(), nextInt()
	g := newGraph(n)
	uf := newUnionFind(n)
	for i := 0; i < m; i++ {
		a, b := nextInt()-1, nextInt()-1
		g.addEdge(a, b)
		uf.union(a, b)
	}
	g.scc()
	for i := 1; i < n; i++ {
		uf.find(0, i)
	}
	sccSize := make([]int, n)
	for i := 0; i < n; i++ {
		sccSize[uf.id[i]] = max(sccSize[uf.id[i]], g.sccSize[g.sccID[i]])
	}
	res := n
	for i := 0; i < n; i++ {
		if sccSize[i] == 1 {
			res--
		}
	}
	fmt.Println(res)
}

package main

import (
	"bufio"
	"fmt"
	"os"
	"strconv"
)

type graph struct {
	V       int     // The number of vetices
	E       [][]int // Adjacency list expression of the graph
	R       [][]int // Reversed E
	vs      []int   // Post order
	visited []bool
	top     []int // Topological order
}

func newGraph(size int) *graph {
	g := &graph{
		V:       size,
		E:       make([][]int, size),
		R:       make([][]int, size),
		vs:      make([]int, 0, size),
		visited: make([]bool, size),
		top:     make([]int, size),
	}
	return g
}

func (g *graph) addEdge(from, to int) {
	g.E[from] = append(g.E[from], to)
	g.R[to] = append(g.R[to], from)
}

func (g *graph) dfs(v int) {
	g.visited[v] = true
	for i, n := 0, len(g.E[v]); i < n; i++ {
		if !g.visited[g.E[v][i]] {
			g.dfs(g.E[v][i])
		}
	}
	g.vs = append(g.vs, v)
}

func (g *graph) rdfs(v, k int) {
	g.visited[v] = true
	g.top[v] = k
	for i, n := 0, len(g.R[v]); i < n; i++ {
		if !g.visited[g.R[v][i]] {
			g.dfs(g.R[v][i])
		}
	}
}

func (g *graph) scc() (k int) {
	g.visited = make([]bool, g.V)
	g.vs = g.vs[:0]
	for i := 0; i < g.V; i++ {
		if !g.visited[i] {
			g.dfs(i)
		}
	}
	g.visited = make([]bool, g.V)
	for i := len(g.vs) - 1; i >= 0; i-- {
		if !g.visited[g.vs[i]] {
			g.rdfs(g.vs[i], k)
			k++
		}
	}
	return k
}

var sc = bufio.NewScanner(os.Stdin)

func next() string {
	sc.Split(bufio.ScanWords)
	if !sc.Scan() {
		panic("could not scan a word from the reader")
	}
	return sc.Text()
}

func nextInt() int {
	i, e := strconv.Atoi(next())
	if e != nil {
		panic(e)
	}
	return i
}

func nextLong() int64 {
	i, e := strconv.ParseInt(next(), 10, 64)
	if e != nil {
		panic(e)
	}
	return i
}

func nextLine() string {
	sc.Split(bufio.ScanLines)
	if !sc.Scan() {
		panic("could not scan a line from the reader")
	}
	return sc.Text()
}

type unionFind struct {
	id []int
	sz []int
}

func newUnionFind(size int) *unionFind {
	uf := &unionFind{
		id: make([]int, size),
		sz: make([]int, size),
	}
	for i := 0; i < size; i++ {
		uf.id[i] = i
		uf.sz[i] = 1
	}
	return uf
}

func (uf *unionFind) root(i int) int {
	for i != uf.id[i] {
		uf.id[i] = uf.id[uf.id[i]]
		i = uf.id[i]
	}
	return i
}

func (uf *unionFind) find(p, q int) bool {
	return uf.root(p) == uf.root(q)
}

func (uf *unionFind) union(p, q int) {
	i, j := uf.root(p), uf.root(q)
	if uf.sz[i] < uf.sz[j] {
		uf.id[i] = j
		uf.sz[j] += uf.sz[i]
	} else {
		uf.id[j] = i
		uf.sz[i] += uf.sz[j]
	}
}

func main() {
	n, m := nextInt(), nextInt()
	res := n
	g := newGraph(n)
	uf := newUnionFind(n)
	for i := 0; i < m; i++ {
		a, b := nextInt()-1, nextInt()-1
		g.addEdge(a, b)
		uf.union(a, b)
	}
	cc := make(map[int][]int)
	for i := 0; i < n; i++ {
		cc[uf.id[i]] = append(cc[uf.id[i]], i)
	}
	res -= len(cc)
	for _, vs := range cc {
		sg := newGraph(g.V)
		for _, v := range vs {
			sg.E[v] = g.E[v]
			sg.R[v] = g.R[v]
		}
		if sg.V > sg.scc() {
			res++
		}
	}
	fmt.Println(res)
}

package main

import (
	"bufio"
	"fmt"
	"os"
	"strconv"
)

type graph struct {
	V       int     // The number of vetices
	E       [][]int // Adjacency list expression of the graph
	R       [][]int // Reversed E
	vs      []int   // Post order
	visited []bool
	top     []int // Topological order
	sccSize []int
}

func newGraph(size int) *graph {
	g := &graph{
		V:       size,
		E:       make([][]int, size),
		R:       make([][]int, size),
		vs:      make([]int, 0, size),
		visited: make([]bool, size),
		top:     make([]int, size),
		sccSize: make([]int, size),
	}
	return g
}

func (g *graph) addEdge(from, to int) {
	g.E[from] = append(g.E[from], to)
	g.R[to] = append(g.R[to], from)
}

func (g *graph) dfs(v int) {
	g.visited[v] = true
	for i, n := 0, len(g.E[v]); i < n; i++ {
		if !g.visited[g.E[v][i]] {
			g.dfs(g.E[v][i])
		}
	}
	g.vs = append(g.vs, v)
}

func (g *graph) rdfs(v, k int) {
	g.visited[v] = true
	g.top[v] = k
	g.sccSize[k]++
	for i, n := 0, len(g.R[v]); i < n; i++ {
		if !g.visited[g.R[v][i]] {
			g.rdfs(g.R[v][i], k)
		}
	}
}

func (g *graph) scc() (k int) {
	g.visited = make([]bool, g.V)
	g.vs = g.vs[:0]
	for i := 0; i < g.V; i++ {
		if !g.visited[i] {
			g.dfs(i)
		}
	}
	g.visited = make([]bool, g.V)
	for i := len(g.vs) - 1; i >= 0; i-- {
		if !g.visited[g.vs[i]] {
			g.rdfs(g.vs[i], k)
			k++
		}
	}
	return k
}

var sc = bufio.NewScanner(os.Stdin)

func next() string {
	sc.Split(bufio.ScanWords)
	if !sc.Scan() {
		panic("could not scan a word from the reader")
	}
	return sc.Text()
}

func nextInt() int {
	i, e := strconv.Atoi(next())
	if e != nil {
		panic(e)
	}
	return i
}

func nextLong() int64 {
	i, e := strconv.ParseInt(next(), 10, 64)
	if e != nil {
		panic(e)
	}
	return i
}

func nextLine() string {
	sc.Split(bufio.ScanLines)
	if !sc.Scan() {
		panic("could not scan a line from the reader")
	}
	return sc.Text()
}

type unionFind struct {
	id []int
	sz []int
}

func newUnionFind(size int) *unionFind {
	uf := &unionFind{
		id: make([]int, size),
		sz: make([]int, size),
	}
	for i := 0; i < size; i++ {
		uf.id[i] = i
		uf.sz[i] = 1
	}
	return uf
}

func (uf *unionFind) root(i int) int {
	for i != uf.id[i] {
		uf.id[i] = uf.id[uf.id[i]]
		i = uf.id[i]
	}
	return i
}

func (uf *unionFind) find(p, q int) bool {
	return uf.root(p) == uf.root(q)
}

func (uf *unionFind) union(p, q int) {
	i, j := uf.root(p), uf.root(q)
	if uf.sz[i] < uf.sz[j] {
		uf.id[i] = j
		uf.sz[j] += uf.sz[i]
	} else {
		uf.id[j] = i
		uf.sz[i] += uf.sz[j]
	}
}

func main() {
	n, m := nextInt(), nextInt()
	g := newGraph(n)
	uf := newUnionFind(n)
	for i := 0; i < m; i++ {
		a, b := nextInt()-1, nextInt()-1
		g.addEdge(a, b)
		uf.union(a, b)
	}
	g.scc()
	ccs, looped := make(map[int]bool), make(map[int]bool)
	for i := 0; i < n; i++ {
		ccs[uf.id[i]] = true
		if g.sccSize[g.top[i]] > 1 {
			looped[uf.id[i]] = true
		}
	}
	fmt.Println(n - len(ccs) + len(looped))
}

package main

import (
	"bufio"
	"fmt"
	"os"
	"strconv"
)

type graph struct {
	V       int     // The number of vetices
	E       [][]int // Adjacency list expression of the graph
	R       [][]int // Reversed E
	vs      []int   // Post order
	visited []bool  // True if the vertex is visited during DFS
	topID   []int   // Topological order
	sccSize []int   // The size of SCC indexed by topID
}

func newGraph(size int) *graph {
	g := &graph{
		V:       size,
		E:       make([][]int, size),
		R:       make([][]int, size),
		vs:      make([]int, 0, size),
		visited: make([]bool, size),
		topID:   make([]int, size),
		sccSize: make([]int, size),
	}
	return g
}

func (g *graph) addEdge(from, to int) {
	g.E[from] = append(g.E[from], to)
	g.R[to] = append(g.R[to], from)
}

func (g *graph) dfs(v int) {
	g.visited[v] = true
	for i, n := 0, len(g.E[v]); i < n; i++ {
		if !g.visited[g.E[v][i]] {
			g.dfs(g.E[v][i])
		}
	}
	g.vs = append(g.vs, v)
}

func (g *graph) rdfs(v, k int) {
	g.visited[v] = true
	g.topID[v] = k
	g.sccSize[k]++
	for i, n := 0, len(g.R[v]); i < n; i++ {
		if !g.visited[g.R[v][i]] {
			g.rdfs(g.R[v][i], k)
		}
	}
}

func (g *graph) scc() (k int) {
	g.visited = make([]bool, g.V)
	g.vs = g.vs[:0]
	for i := 0; i < g.V; i++ {
		if !g.visited[i] {
			g.dfs(i)
		}
	}
	g.visited = make([]bool, g.V)
	for i := len(g.vs) - 1; i >= 0; i-- {
		if !g.visited[g.vs[i]] {
			g.rdfs(g.vs[i], k)
			k++
		}
	}
	return k
}

var sc = bufio.NewScanner(os.Stdin)

func next() string {
	sc.Split(bufio.ScanWords)
	if !sc.Scan() {
		panic("could not scan a word from the reader")
	}
	return sc.Text()
}

func nextInt() int {
	i, e := strconv.Atoi(next())
	if e != nil {
		panic(e)
	}
	return i
}

func nextLong() int64 {
	i, e := strconv.ParseInt(next(), 10, 64)
	if e != nil {
		panic(e)
	}
	return i
}

func nextLine() string {
	sc.Split(bufio.ScanLines)
	if !sc.Scan() {
		panic("could not scan a line from the reader")
	}
	return sc.Text()
}

type unionFind struct {
	id []int
	sz []int
}

func newUnionFind(size int) *unionFind {
	uf := &unionFind{
		id: make([]int, size),
		sz: make([]int, size),
	}
	for i := 0; i < size; i++ {
		uf.id[i] = i
		uf.sz[i] = 1
	}
	return uf
}

func (uf *unionFind) root(i int) int {
	for i != uf.id[i] {
		uf.id[i] = uf.id[uf.id[i]]
		i = uf.id[i]
	}
	return i
}

func (uf *unionFind) find(p, q int) bool {
	return uf.root(p) == uf.root(q)
}

func (uf *unionFind) union(p, q int) {
	i, j := uf.root(p), uf.root(q)
	if uf.sz[i] < uf.sz[j] {
		uf.id[i] = j
		uf.sz[j] += uf.sz[i]
	} else {
		uf.id[j] = i
		uf.sz[i] += uf.sz[j]
	}
}

func max(x, y int) int {
	if y > x {
		return y
	}
	return x
}

func main() {
	n, m := nextInt(), nextInt()
	g := newGraph(n)
	uf := newUnionFind(n)
	for i := 0; i < m; i++ {
		a, b := nextInt()-1, nextInt()-1
		g.addEdge(a, b)
		uf.union(a, b)
	}
	g.scc()
	maxSccSize := make(map[int]int)
	for i := 0; i < n; i++ {
		maxSccSize[uf.id[i]] = max(maxSccSize[uf.id[i]], g.sccSize[g.topID[i]])
	}
	res := n
	for _, x := range maxSccSize {
		if x < 2 {
			res--
		}
	}
	fmt.Println(res)
}

package main

import (
	"bufio"
	"fmt"
	"os"
	"strconv"
)

type graph struct {
	V       int     // The number of vetices
	E       [][]int // Adjacency list expression of the graph
	R       [][]int // Reversed E
	vs      []int   // Post order
	visited []bool
	top     []int // Topological order
}

func newGraph(size int) *graph {
	g := &graph{
		V:       size,
		E:       make([][]int, size),
		R:       make([][]int, size),
		vs:      make([]int, 0, size),
		visited: make([]bool, size),
		top:     make([]int, size),
	}
	return g
}

func (g *graph) addEdge(from, to int) {
	g.E[from] = append(g.E[from], to)
	g.R[to] = append(g.R[to], from)
}

func (g *graph) dfs(v int) {
	g.visited[v] = true
	for i, n := 0, len(g.E[v]); i < n; i++ {
		if !g.visited[g.E[v][i]] {
			g.dfs(g.E[v][i])
		}
	}
	g.vs = append(g.vs, v)
}

func (g *graph) rdfs(v, k int) {
	g.visited[v] = true
	g.top[v] = k
	for i, n := 0, len(g.R[v]); i < n; i++ {
		if !g.visited[g.R[v][i]] {
			g.dfs(g.R[v][i])
		}
	}
}

func (g *graph) scc() (k int) {
	g.visited = make([]bool, g.V)
	g.vs = g.vs[:0]
	for i := 0; i < g.V; i++ {
		if !g.visited[i] {
			g.dfs(i)
		}
	}
	g.visited = make([]bool, g.V)
	for i := len(g.vs) - 1; i >= 0; i-- {
		if !g.visited[g.vs[i]] {
			g.rdfs(g.vs[i], k)
			k++
		}
	}
	return k
}

var sc = bufio.NewScanner(os.Stdin)

func next() string {
	sc.Split(bufio.ScanWords)
	if !sc.Scan() {
		panic("could not scan a word from the reader")
	}
	return sc.Text()
}

func nextInt() int {
	i, e := strconv.Atoi(next())
	if e != nil {
		panic(e)
	}
	return i
}

func nextLong() int64 {
	i, e := strconv.ParseInt(next(), 10, 64)
	if e != nil {
		panic(e)
	}
	return i
}

func nextLine() string {
	sc.Split(bufio.ScanLines)
	if !sc.Scan() {
		panic("could not scan a line from the reader")
	}
	return sc.Text()
}

type unionFind struct {
	id []int
	sz []int
}

func newUnionFind(size int) *unionFind {
	uf := &unionFind{
		id: make([]int, size),
		sz: make([]int, size),
	}
	for i := 0; i < size; i++ {
		uf.id[i] = i
		uf.sz[i] = 1
	}
	return uf
}

func (uf *unionFind) root(i int) int {
	for i != uf.id[i] {
		uf.id[i] = uf.id[uf.id[i]]
		i = uf.id[i]
	}
	return i
}

func (uf *unionFind) find(p, q int) bool {
	return uf.root(p) == uf.root(q)
}

func (uf *unionFind) union(p, q int) {
	i, j := uf.root(p), uf.root(q)
	if uf.sz[i] < uf.sz[j] {
		uf.id[i] = j
		uf.sz[j] += uf.sz[i]
	} else {
		uf.id[j] = i
		uf.sz[i] += uf.sz[j]
	}
}

func main() {
	var res int
	n, m := nextInt(), nextInt()
	g := newGraph(n)
	uf := newUnionFind(n)
	for i := 0; i < m; i++ {
		a, b := nextInt()-1, nextInt()-1
		g.addEdge(a, b)
		uf.union(a, b)
	}
	cc := make(map[int][]int)
	for i := 0; i < n; i++ {
		cc[uf.id[i]] = append(cc[uf.id[i]], i)
	}
	for _, vs := range cc {
		sg := newGraph(n)
		for _, v := range vs {
			sg.E[v] = g.E[v]
			sg.R[v] = g.R[v]
		}
		if sg.V > sg.scc() {
			res += len(vs)
		} else {
			res += len(vs) - 1
		}
	}
	fmt.Println(res)
}

package main

import (
	"bufio"
	"fmt"
	"os"
	"strconv"
)

var sc = bufio.NewScanner(os.Stdin)

func next() string {
	sc.Split(bufio.ScanWords)
	if !sc.Scan() {
		panic("could not scan a word from the reader")
	}
	return sc.Text()
}

func nextInt() int {
	i, e := strconv.Atoi(next())
	if e != nil {
		panic(e)
	}
	return i
}

func nextLong() int64 {
	i, e := strconv.ParseInt(next(), 10, 64)
	if e != nil {
		panic(e)
	}
	return i
}

func nextLine() string {
	sc.Split(bufio.ScanLines)
	if !sc.Scan() {
		panic("could not scan a line from the reader")
	}
	return sc.Text()
}

type graph struct {
	V       int     // The number of vetices
	E       [][]int // Adjacency list expression of the graph
	R       [][]int // Reversed E
	vs      []int   // Post order
	visited []bool  // True if the vertex is visited during DFS
	sccID   []int   // Topological order of the vertex v
	sccSize []int   // The size of SCC indexed by sccID
}

func newGraph(size int) *graph {
	g := &graph{
		V:       size,
		E:       make([][]int, size),
		R:       make([][]int, size),
		vs:      make([]int, 0, size),
		visited: make([]bool, size),
		sccID:   make([]int, size),
		sccSize: make([]int, size),
	}
	return g
}

func (g *graph) addEdge(from, to int) {
	g.E[from] = append(g.E[from], to)
	g.R[to] = append(g.R[to], from)
}

func (g *graph) dfs(v int) {
	g.visited[v] = true
	for i, n := 0, len(g.E[v]); i < n; i++ {
		if !g.visited[g.E[v][i]] {
			g.dfs(g.E[v][i])
		}
	}
	g.vs = append(g.vs, v)
}

func (g *graph) rdfs(v, k int) {
	g.visited[v] = true
	g.sccID[v] = k
	g.sccSize[k]++
	for i, n := 0, len(g.R[v]); i < n; i++ {
		if !g.visited[g.R[v][i]] {
			g.rdfs(g.R[v][i], k)
		}
	}
}

func (g *graph) scc() (k int) {
	g.visited = make([]bool, g.V)
	g.vs = g.vs[:0]
	for i := 0; i < g.V; i++ {
		if !g.visited[i] {
			g.dfs(i)
		}
	}
	g.visited = make([]bool, g.V)
	for i := len(g.vs) - 1; i >= 0; i-- {
		if !g.visited[g.vs[i]] {
			g.rdfs(g.vs[i], k)
			k++
		}
	}
	return k
}

func max(x, y int) int {
	if y > x {
		return y
	}
	return x
}

type unionFind struct {
	id []int
	sz []int
}

func newUnionFind(size int) *unionFind {
	uf := &unionFind{
		id: make([]int, size),
		sz: make([]int, size),
	}
	for i := 0; i < size; i++ {
		uf.id[i] = i
		uf.sz[i] = 1
	}
	return uf
}

func (uf *unionFind) root(x int) int {
	if uf.id[x] == x {
		return x
	}
	uf.id[x] = uf.root(uf.id[x])
	return uf.id[x]
}

func (uf *unionFind) find(p, q int) bool {
	return uf.root(p) == uf.root(q)
}

func (uf *unionFind) union(p, q int) {
	i, j := uf.root(p), uf.root(q)
	if uf.sz[i] < uf.sz[j] {
		uf.id[i] = j
		uf.sz[j] += uf.sz[i]
	} else {
		uf.id[j] = i
		uf.sz[i] += uf.sz[j]
	}
}

func (g *graph) dfs2(v int) (z int) {
	g.visited[v] = true
	z = g.sccSize[g.sccID[v]]
	for i, n := 0, len(g.E[v]); i < n; i++ {
		if !g.visited[g.E[v][i]] {
			z = max(z, g.dfs2(g.E[v][i]))
		}
	}
	for i, n := 0, len(g.R[v]); i < n; i++ {
		if !g.visited[g.R[v][i]] {
			z = max(z, g.dfs2(g.R[v][i]))
		}
	}
	return
}

func main() {
	n, m := nextInt(), nextInt()
	g := newGraph(n)
	uf := newUnionFind(n)
	for i := 0; i < m; i++ {
		a, b := nextInt()-1, nextInt()-1
		g.addEdge(a, b)
		uf.union(a, b)
	}
	g.scc()
	for i := 0; i < n; i++ {
		uf.root(i)
	}
	fmt.Println(uf.id)
	sccSize := make([]int, n)
	for i := 0; i < n; i++ {
		sccSize[uf.id[i]] = max(sccSize[uf.id[i]], g.sccSize[g.sccID[i]])
	}
	res := n
	for i := 0; i < n; i++ {
		if sccSize[i] == 1 {
			res--
		}
	}
	fmt.Println(res)
}