Problem:
Score : 800 points

Problem Statement

You are given a string S consisting of lowercase English letters.
Determine whether we can turn S into a palindrome by repeating the operation of swapping two adjacent characters. If it is possible, find the minimum required number of operations.

Constraints

1 \leq |S| \leq 2 × 10^5

S consists of lowercase English letters.

Input

Input is given from Standard Input in the following format:

S

Output

If we cannot turn S into a palindrome, print -1. Otherwise, print the minimum required number of operations.

Sample Input 1

eel

Sample Output 1

1

We can turn S into a palindrome by the following operation:

Swap the 2-nd and 3-rd characters. S is now ele.

Sample Input 2

ataatmma

Sample Output 2

4

We can turn S into a palindrome by the following operation:

Swap the 5-th and 6-th characters. S is now ataamtma.

Swap the 4-th and 5-th characters. S is now atamatma.

Swap the 3-rd and 4-th characters. S is now atmaatma.

Swap the 2-nd and 3-rd characters. S is now amtaatma.

Sample Input 3

snuke

Sample Output 3

-1

We cannot turn S into a palindrome.

Solution in C# (Mono 4.6.2.0) (judge verdict: Wrong Answer)

using System;
using System.Collections;
using System.Collections.Generic;
using System.Text;
using System.Linq;
using static MyIO;


public class E
{
	public static void Main()
	{
		string S = GetString();
		int N = S.Length;
		int[] num = new int[26];
		for(int i = 0; i < N; i++)
			num[(int)(S[i] - 'a')]++;

		if(num.Count(x => x % 2 == 1) > 1)
		{
			Console.WriteLine(-1);
			return;
		}

		int[] p = new int[N];
		var queues = Enumerable.Range(0, 26).Select(_ => new Queue<int>()).ToArray();
		bool[] moved = new bool[N];
		int[] used = new int[26];
		int left = 1;
		for(int i = 0; i < N; i++)
		{
			int c = (int)(S[i] - 'a');
			if(used[c] >= num[c] / 2)
			{
				if(num[c] % 2 == 1)
				{
					p[i] = (N + 1) / 2;
					moved[i] = true;
					used[c]++;
				}

				continue;
			}
			
			p[i] = left;
			queues[c].Enqueue(N - left + 1);
			left++;
			moved[i] = true;
			used[c]++;
		}

		for(int i = N - 1; i >= 0; i--)
		{
			if(moved[i])
				continue;
			
			int c = (int)(S[i] - 'a');
			p[i] = queues[c].Dequeue();
		}

		long ans = 0;
		var bit = new BinaryIndexedTree<int>(N, 0, (x, y) => x + y);
		for(int i = 0; i < N; i++)
		{
			ans += i - bit.Query(p[i]);
			bit.Update(p[i], 1);
		}
		Console.WriteLine(ans);
	}
}


public class BinaryIndexedTree<T>
{
	private int N;
	private T Identity;
	private Func<T, T, T> Func;
	private T[] bit;

	public BinaryIndexedTree(int n, T identity, Func<T, T, T> func)
	{
		N = n;
		Identity = identity;
		Func = func;
			
		bit = new T[N + 1];  // 1-index
		for(int i = 0; i <= N; i++)
			bit[i] = Identity;
	}

	public void Update(int i, T x)
	{
		while(i <= N)
		{
			bit[i] = Func(bit[i], x);
			i += i & -i;
		}
	}

	public T Query(int i)
	{
		T s = Identity;
		while(i > 0)
		{
			s = Func(s, bit[i]);
			i -= i & -i;
		}
		return s;
	}

	/* bit must be monotonically increasing */
	public int LowerBound(T key, Comparison<T> comp, Func<T, T, T> inv)
	{
		if(comp(key, Identity) <= 0)
			return 0;

		int pow = 1;
		while(pow <= N)
			pow <<= 1;
		pow >>= 1;

		int x = 0;
		for(int k = pow; k > 0; k >>= 1)
		{
			if((x + k <= N) && (comp(bit[x + k], key) < 0))
			{
				key = inv(key, bit[x + k]);
				x += k;
			}
		}

		return x + 1;
	}
}


public static class MyIO
{
	private static string[] args = null;
	private static int num = -1;
	private static int used = -1;

	private static string getArg()
	{
		if(used == num)
		{
			args = Console.ReadLine().Split(' ');
			num = args.Length;
			used = 0;
		}
		return args[used++];
	}

	public static int GetInt(){ return int.Parse(getArg()); }
	public static long GetLong(){ return long.Parse(getArg()); }
	public static double GetDouble(){ return double.Parse(getArg()); }
	public static string GetString(){ return getArg(); }
}