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.Linq;
using System.Text;

class TEST{
	static void Main(){
		Sol mySol =new Sol();
		mySol.Solve();
	}
}

class Sol{
	public void Solve(){
		
		int N = S.Length;
		int[] cnt = new int[256];
		for(int i=0;i<N;i++){
			cnt[S[i]]++;
		}
		
		char xx = (char) 0;
		char odd = xx;
		for(int i=0;i<256;i++){
			if(cnt[i] % 2 == 1){
				if(odd == xx){
					odd = (char)i;
				} else {
					Console.WriteLine(-1);
					return;
				}
			}
		}
		
		
		var ca = S.ToCharArray();
		int[] L = new int[256];
		int[] R = new int[256];
		for(char c = 'a'; c <= 'z'; c++){
			L[c] = N;
			R[c] = -1;
		}
		
		for(int i=0;i<N;i++){
			L[S[i]] = Math.Min(L[S[i]],i);
			R[S[i]] = Math.Max(R[S[i]],i);
		}
		
		int tot = 0;
		if(odd != xx){
			int t = N / 2;
			int now = L[odd];
			while(now != t){
				if(t < now){
					Swap(ref ca[now], ref ca[now - 1]);
					tot++;
					now--;
				} else {
					Swap(ref ca[now], ref ca[now + 1]);
					tot++;
					now++;
				}
			}
		}
		
		int l = 0;
		int r = N - 1;
		
		var ST = new SegTree[26];
		for(int i=0;i<26;i++) ST[i] = new SegTree(N);
		for(int i=0;i<N;i++){
			ST[ca[i] - 'a'].Update(i,1);
		}
		
		
		
		while(l < r){
		
			if(ca[l] == ca[r]){
				l++; r--;
				continue;
			}
			int moveleft = ST[ca[r] - 'a'].QueryL(l,r) - l;
			int moveright = r - ST[ca[l] - 'a'].QueryR(l,r);
			if(moveleft < moveright){
				int now = l + moveleft;
				while(now > l){
					ST[ca[now] - 'a'].Update(now,0);
					ST[ca[now] - 'a'].Update(now - 1,1);
					ST[ca[now-1] - 'a'].Update(now - 1,0);
					ST[ca[now-1] - 'a'].Update(now ,1);
					Swap(ref ca[now], ref ca[now - 1]);
					tot++;
					now--;
				}
			} else {
				int now = r - moveleft;
				while(now < r){
					ST[ca[now] - 'a'].Update(now,0);
					ST[ca[now] - 'a'].Update(now + 1,1);
					ST[ca[now-1] - 'a'].Update(now + 1,0);
					ST[ca[now-1] - 'a'].Update(now ,1);
					Swap(ref ca[now], ref ca[now + 1]);
					tot++;
					now++;
				}
			}
			l++;r--;
		}
		
		
		
		Console.WriteLine(tot);
	}
	
	void Swap<T>(ref T a, ref T b){
		var t = a; a = b; b = t;
	}
	
	String S;
	public Sol(){
		S = rs();
	}

	static String rs(){return Console.ReadLine();}
	static int ri(){return int.Parse(Console.ReadLine());}
	static long rl(){return long.Parse(Console.ReadLine());}
	static double rd(){return double.Parse(Console.ReadLine());}
	static String[] rsa(char sep=' '){return Console.ReadLine().Split(sep);}
	static int[] ria(char sep=' '){return Array.ConvertAll(Console.ReadLine().Split(sep),e=>int.Parse(e));}
	static long[] rla(char sep=' '){return Array.ConvertAll(Console.ReadLine().Split(sep),e=>long.Parse(e));}
	static double[] rda(char sep=' '){return Array.ConvertAll(Console.ReadLine().Split(sep),e=>double.Parse(e));}
}



class SegTree{
	//segment Tree 
	// 0-origin
	public int[] Data;	
	public int[] L,R;
	public int Inf;	
	public int N;		//size 
	public int n;		//size (power of 2);
	
	// constructor
	public SegTree(int n_){
		N=n_;Inf = (int) -1;
		n = 1;
		while(n < n_) n *= 2;
		Data = new int[2*n - 1];
		L = new int[2*n - 1];
		R = new int[2*n - 1];
		for(int i=0;i<2*n-1;i++){
			Data[i] = Inf;
			L[i] = N;
			R[i] = -1;
		}
	}
	
	//	   0
	//	 1   2
	//	3 4 5 6
	public void Update(int k, int a){
		k+=n-1;	
		Data[k]=a;
		L[k] = k - (n - 1);
		R[k] = k - (n - 1);
		while(k>0){
			k=(k-1)/2;
			Data[k] = Math.Max(Data[k*2+1], Data[k*2+2]);
			L[k] = Data[k*2+1] >= Data[k*2+2] ? L[k*2+1] : L[k*2+2];
			R[k] = Data[k*2+1] > Data[k*2+2] ? R[k*2+1] : R[k*2+2];
		}
	}
	
	public int QueryL(int a, int b){
		return QueryLeft(a, b, 0, 0, n);
	}
	public int QueryR(int a, int b){
		return QueryRight(a, b, 0, 0, n);
	}

	public int Query(int a,int b,int k,int l,int r){
		// [a,b) not overwraps [l,r) => return Inf
		if(r<=a || b<=l) return Inf;
		// [a,b) include [l,r) => return Data[k];
		if(a<=l && r<=b)return Data[k];
		// or return min(left,right)
		var vl = Query(a,b,k*2+1,l,(l+r)/2);
		var vr = Query(a,b,k*2+2,(l+r)/2,r);
		return Math.Max(vl,vr);
	}
	public int QueryLeft(int a,int b,int k,int l,int r){
		// [a,b) not overwraps [l,r) => return Inf
		if(r<=a || b<=l) return -1;
		// [a,b) include [l,r) => return Data[k];
		if(a<=l && r<=b) return L[k];
		// or return min(left,right)
		var vl = Query(a,b,k*2+1,l,(l+r)/2);
		var vr = Query(a,b,k*2+2,(l+r)/2,r);
		var vlidx = QueryLeft(a,b,k*2+1,l,(l+r)/2);
		var vridx = QueryLeft(a,b,k*2+2,(l+r)/2,r);
		return vl >= vr ? vlidx : vridx;
	}
	public int QueryRight(int a,int b,int k,int l,int r){
		// [a,b) not overwraps [l,r) => return Inf
		if(r<=a || b<=l) return -1;
		// [a,b) include [l,r) => return Data[k];
		if(a<=l && r<=b) return L[k];
		// or return min(left,right)
		var vl = Query(a,b,k*2+1,l,(l+r)/2);
		var vr = Query(a,b,k*2+2,(l+r)/2,r);
		var vlidx = QueryRight(a,b,k*2+1,l,(l+r)/2);
		var vridx = QueryRight(a,b,k*2+2,(l+r)/2,r);
		return vl > vr ? vlidx : vridx;
	}
	
}