// Java program to implement
// the above approach
import java.io.*;
import java.lang.*;
import java.util.*;
class GFG{
// Function to add index of the deleted character
static void add_seg(int seg[], int start, int end,
int current, int index)
{
// If index is beyond the range
if (index > end || index < start)
return;
// Insert the index of the deleted
// character
if (start == end)
{
seg[current] = 1;
return;
}
int mid = (start + end) / 2;
// Search over the subtrees to find the
// desired index
add_seg(seg, start, mid, 2 * current + 1, index);
add_seg(seg, mid + 1, end, 2 * current + 2, index);
seg[current] = seg[2 * current + 1] +
seg[2 * current + 2];
}
// Function to return count of deleted indices
// which are to the left of the current index
static int deleted(int seg[], int l, int r, int start,
int end, int current)
{
if (end < l || start > r)
return 0;
if (start >= l && end <= r)
return seg[current];
int mid = (start + end) / 2;
return deleted(seg, l, r, start, mid,
2 * current + 1) +
deleted(seg, l, r, mid + 1, end,
2 * current + 2);
}
// Function to generate the
// sum of indices
static void sumOfIndices(String s)
{
int N = s.length();
int x = (int)(Math.ceil(Math.log(N) / Math.log(2)));
int seg_size = 2 * (int)Math.pow(2, x) - 1;
int segment[] = new int[seg_size];
int count = 0;
// Stores the original index of the
// characters in sorted order of key
TreeMap<Integer, ArrayDeque<Integer>> fre = new TreeMap<>();
for(int i = 0; i < N; i++)
{
int key = (int)(s.charAt(i));
ArrayDeque<Integer> que = fre.getOrDefault(
key, new ArrayDeque<>());
que.addLast(i);
fre.put(key, que);
}
// Traverse the map
while (!fre.isEmpty())
{
// Extract smallest index
// of smallest character
int it = fre.firstKey();
// Delete the character from the map
// if it has no remaining occurrence
if (fre.get(it).size() == 0)
fre.remove(it);
else
{
ArrayDeque<Integer> que = fre.get(it);
// Stores the original index
int original_index = que.getFirst();
// System.out.println(original_index);
// Count of elements removed to
// the left of current character
int curr_index = deleted(segment, 0,
original_index - 1,
0, N - 1, 0);
// Current index of the current character
int new_index = original_index - curr_index;
// For 1-based indexing
count += new_index + 1;
// Insert the deleted index
// in the segment tree
add_seg(segment, 0, N - 1, 0,
original_index);
que.removeFirst();
fre.put(it, que);
}
}
// Final answer
System.out.println(count);
}
// Driver Code
public static void main(String[] args)
{
String s = "geeksforgeeks";
sumOfIndices(s);
}
}
// This code is contributed by Kingash