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: Accepted)

using System;
using System.Linq;//リストの使用
using System.Collections.Generic;
class Program
{
static string ss = Console.ReadLine();
static string alphabets = "abcdefghijklmnopqrstuvwxyz";//26文字
static long[] alphaCount = new long[26];
static bool isPossible = true;//並び替え可能か？
static long[] origiStringNums = new long[ss.Length];
static long[] lookedAlphaCount = new long[26];
static long[] bits = new long[ss.Length+1];
static int[] s = ss.Select(c => c - 'a').ToArray();
static long writeNum = 1;
static long[][] leftMemo = new long[26][];
static long oddMemo = 0;
static long oddMemoSub = 0;
	static void Main()
	{
    
    for(long stNum = 0; stNum < s.Length; stNum++)
    {
          alphaCount[s[stNum]]++;
    }

    if(s.Length % 2 == 0)
    {
    isPossible = true;
      for(long i = 0; i < 26; i++)
      {
        if(alphaCount[i] % 2 == 1) isPossible = false;
      }
    }else
    {
    long addMemo = 0;
    isPossible = false;
      for(long i = 0; i < 26; i++)
      {
      if(alphaCount[i] % 2 == 1)
        {
          addMemo++;
          oddMemo = alphaCount[i];
        }
      }
    if(addMemo == 1) isPossible = true;
    }

    if(!(isPossible))
    {
		Console.WriteLine(-1);
    }else
    {
      writeNum = 1;
    
    //Console.WriteLine(alphaCount[0]+" "+alphaCount[1]);
      for(long stNum = 0; stNum < s.Length; stNum++)
      {
        if(lookedAlphaCount[s[stNum]] < alphaCount[s[stNum]]/2)
          {
          lookedAlphaCount[s[stNum]]++;
          origiStringNums[stNum] = writeNum;
          writeNum++;
          }else if(alphaCount[s[stNum]] % 2 == 1 && 
            lookedAlphaCount[s[stNum]] == (alphaCount[s[stNum]]-1)/2)
          {
            lookedAlphaCount[s[stNum]]++;
            origiStringNums[stNum] = s.Length / 2 + 1;
          }
      }
    //Console.WriteLine(origiStringNums[0]+" "+origiStringNums[1]+" "+origiStringNums[2]);
    if(s.Length % 2 == 1) writeNum++;

      for(long i = 0; i < 26; i++)
      {
        leftMemo[i] = new long[alphaCount[i]/2+3];//ジャグ配列の大きさを確定
      }

      for(long stNum = 0; stNum < s.Length; stNum++)
      {
        if(origiStringNums[stNum] != 0)
          {
            leftMemo[s[stNum]][leftMemo[s[stNum]][0]+1] = origiStringNums[stNum];
            leftMemo[s[stNum]][0]++;
          }
      }

      for(long i = 0; i < 26; i++)
      {
        if(alphaCount[i] % 2 == 1)
        {
          leftMemo[i][0]--;
        }
      }

    for(long stNum = 0; stNum < s.Length; stNum++)//右側のソート
      {
      if(origiStringNums[stNum] == 0)
        {
          origiStringNums[stNum] = 
            s.Length - leftMemo[s[stNum]][leftMemo[s[stNum]][0]] + 1;
          leftMemo[s[stNum]][0]--;
        }
      }
      //Console.WriteLine(origiStringNums[0]+" "+origiStringNums[1]+" "+origiStringNums[2]);

/*
    Console.WriteLine(origiStringNums[0]+" "+origiStringNums[1]+" "+origiStringNums[2]
      +" "+origiStringNums[3]+" "+origiStringNums[4]+" "+origiStringNums[5]
      +" "+origiStringNums[6]+" "+origiStringNums[7]);
*/

    long answer = 0;
    for(long i = 0; i < s.Length; i++)
      {
      answer += i - BitSum(origiStringNums[i]);
      BitAdd(origiStringNums[i], 1);
      }
    
		  Console.WriteLine(answer);
    }
	}



  static void BitAdd(long i, long x)//BITでiだけにx加算
{
  while(i <= s.Length)
  {
    bits[i] += x;
    i += i&-i;
  }
}

static long BitSum(long i)//BITでi以下の総和を計算
{
  long sum = 0;
  while(i > 0)
  {
    sum += bits[i];
    i -= i&-i;
  }
  return sum;
}
}