PROBLEM
Given a string consisting only of r, g and b, we have to find the shortest number of adjacent swaps to group all the similar characters together.
https://www.codechef.com/problems/WPROB/
OR
Olya works as a warehouse keeper for a T-Shirt factory. Now the factory is facing hard times, so currently they produce only the T-shirts of three kinds: red, green and blue T-Shirts. All the T-shirts are stored in the containers, each of the containers contain the T-Shirts of a single colour.
Now there are N containers at the warehouse, lined up in a line. Let's enumerate the containers by the positive integers from 1 to N, starting from the leftmost and ending at the rightmost one. Their order is described with a string S. Each symbol of this string is either "r", "g" or "b" and denotes the colour of the respective T-shirts, stored in the container.
Olya likes orderliness. She is not satisfied with the fact that different kinds of containers are messed up. So she wants to rearrange the containers in such a way that the number of pairs of adjacent containers that contain the T-shirts of different colors is as minimal as possible.
For doing that, she has a special crane. The crane is capable of doing the following things:
- Take a container with the number X and put it in front of all the containers. This operation takes(X-1) seconds. Note that we are considering the 1-dimensional model of the warehouse, so "in front of all the containers" means to the left of all the containers. The warehouse is so large, so you shouldn't worry about its' size and this operation is always performable.
- Take a container with the number X and take some container to the left of it (say, the container number Y). Remove the container number X from its' position and insert it right after the container with the number Y. This operation will take X-Y-1 seconds.
- Take a container with the number X and take some container to the right of it (say, the container number Y). Remove the container number X from its' position and insert it right after the container with the number Y. This operation will take Y-X seconds.
Note that after the operation, we will re-enumerate the containers from left to right by the positive integers from 1 to N.
Though Olya is keen on orderliness, she doesn't way to stay at the warehouse for long on Sunday. So she asks you to help her and to calculate the minimal possible number of seconds that is necessary to rearrange the containers in the desired way.
Input
The first line of the input contains an integer T denoting the number of test cases. The description of Ttest cases follows.
The first (and only) line of each test case contains a string S, consisting of N symbols denoting the color string corresponding to the containers.
Output
For each test case, output a single line containing the answer to the problem's question for the corresponding test case.
Constraints
- 1 ≤ T ≤ 10
- The string S consists only of the lower-case Latin letters from the set {r, g, b}.
- (Subtask 1): 1 ≤ N = |S| ≤ 7 - 33 points.
- (Subtask 2): 1 ≤ N = |S| ≤ 1000 - 33 points.
- (Subtask 3): 1 ≤ N = |S| ≤ 105 - 34 points.
Example
Input:
4
rgr
rrr
rgb
rgbr
Output:
1
0
0
2
Explanation
Example case 1.We can move the second container to the beginning of the line. This will take one second.
Example case 2.Containers are already in desired way.
Example case 3.Here also, containers are already in desired way.
Example case 4.You can put first r to the just right of b. It will take 2 seconds to do so.
**************************************************EDITORIAL********************************************************************
QUICK EXPLANATION
First, observe that all the moves really reduce down to swapping adjacent elements. Try all the 3! = 6 possible ordering of r, g and b. Now since the order is fixed, rearranging the string to a particular order is the same as sorting using the current order. The number of swaps required to sort an array is the same as the number of inversions.
EXPLANATION
Observe that each of the 3 types of moves reduce to swapping adjacent elements in 1 moment of time.
Assume for the moment that we know in which order the final rearrangement should be in. i.e. suppose the ordering is "rgb", then all the r's must come first followed by all the g's and then all the b's. What is the minimum number of moves required to do this?
Now say s[i] = 'r'. We know that r comes first, so if there is a 'b' or 'g' to the left of it, they must be swapped at some time. So, we can count the number of times b or g occur to the left of i and add them to the current answer. Similarly if s[i] = 'g' and there is a b to the right of i, then they must be swapped. So we count the number of times g occurs before i and add it to the current answer.
TO generalize, if we know the order o=o1o2o3 ( a permutation of r, g and b), we can find the minimum number of swaps to rearrenge the string in that order by looping through the string and keeping a count of the characters of each type we have seen so far. Suppose c1, c2 and c3 are the count of the o1, o2 and o3 seen so far.
We can get the minimum number of swaps as follows:
For i = 0 to len(s) - 1:
if s[i] == o1 cur_ans += c2 + c3
if s[i] == o2 cur_ans += c3
But how do we know which order is optimal? Let us see how many orders are possible. Since there are only 3 possible characters, there are only 3! = 6 possible orderings. So, we can try all possible orders, calculate the minimum number of swaps to achieve that order and take the minimum over all the orders to get the optimal answer.
What we are calculating is the number of inversions in the string given an order. What is an inversion? Intuitively, it is the number of pairs of numbers which are out of order in the array. More formally, the number of inversions of an array a is the number of pairs i < j such that a[i] > a[j]. We will prove that the number of adjacent swaps required to sort an array is equal to the number of inversions in the array.
Claim:
Minimum number of adjacent swap required to sort an array is exactly equal to number of inversions.
Proof:
By making one adjacent swap, we can not kill more than one inversion. So the number of swaps required will be at least equal to the number of inversions. So number of inversions will be a lower bound to number of swaps. We can indeed achieve that lower bound as follows.
Process:
Pick the minimum element (if there are many, pick the leftmost). All the elements which are on the left side of it should be moved to right side of it. For that you can pick the left adjacent element (if it exists) and swap it with minimum element. Keep repeating this step until minimum element is at the leftmost end. Total number of swaps taken are number of position i's such that A[i]>A[minPos] and i<minPos where minPos denotes location where minimum element was found. This is nothing but the number of inversions with minPos as one of the index.
Now remove the minimum element and repeat step 1.
You can notice that this process will sort the array and minimum number of swaps are exactly equal to number of inversions.
Complexity
There is only one loop and that is run a constant (6) number of times. So the complexity is O(n).
*******************************************************CODE (NLOGN)***************************************************
#include<iostream>
using namespace std;
typedef int lli;
typedef int llli;
lli temp[10000000];
#include<bits/stdc++.h>
long long ic=0;
lli merge (lli arr[],llli start,llli mid,llli end)
{
llli i=start, j=mid+1;
llli p=start;
long long lc=0;
while(i<=mid && j<=end)
{
if(arr[i]>arr[j])
{
lc+=mid-i+1;
temp[p++]=arr[j];
j++;
}
else
{
temp[p++]=arr[i++];
}
}
while(i<=mid) temp[p++]=arr[i++];
while(j<=end) temp[p++]=arr[j++];
for(int i=start;i<p;i++) arr[i]=temp[i];
return lc;
}
void divide(lli arr[],llli start,llli end)
{
if(start<end)
{
int mid=(start+end)/2;
divide(arr,start,mid);
divide(arr,mid+1,end);
ic+=merge(arr,start,mid,end);
}
}
int main()
{
int t;
cin>>t;
while(t--)
{
ic=0;
long long ans=1000000000000000LL;
char arr[1000000];
cin>>arr;
llli len=strlen(arr);
lli a[len+10];
// rgb
for(int i=0;i<len;i++)
{
if(arr[i]=='r') a[i]=1;
else if(arr[i]=='g')a[i]=2;
else if(arr[i]=='b')a[i]=3;
}
divide(a,0,len-1);
if(ic<ans) ans=ic;
ic=0;
// rbg
for(int i=0;i<len;i++)
{
if(arr[i]=='r') a[i]=1;
else if(arr[i]=='b')a[i]=2;
else if(arr[i]=='g')a[i]=3;
}
divide(a,0,len-1);
if(ic<ans) ans=ic;
ic=0;
// brg
for(int i=0;i<len;i++)
{
if(arr[i]=='b') a[i]=1;
else if(arr[i]=='r')a[i]=2;
else if(arr[i]=='g')a[i]=3;
}
divide(a,0,len-1);
if(ic<ans) ans=ic;
ic=0;
// bgr
for(int i=0;i<len;i++)
{
if(arr[i]=='b') a[i]=1;
else if(arr[i]=='g')a[i]=2;
else if(arr[i]=='r')a[i]=3;
}
divide(a,0,len-1);
if(ic<ans) ans=ic;
ic=0;
//grb
for(int i=0;i<len;i++)
{
if(arr[i]=='g') a[i]=1;
else if(arr[i]=='r')a[i]=2;
else if(arr[i]=='b')a[i]=3;
}
divide(a,0,len-1);
if(ic<ans) ans=ic;
ic=0;
//gbr
for(int i=0;i<len;i++)
{
if(arr[i]=='g') a[i]=1;
else if(arr[i]=='b')a[i]=2;
else if(arr[i]=='r')a[i]=3;
}
divide(a,0,len-1);
if(ic<ans) ans=ic;
ic=0;
cout<<ans<<endl;
}
return 0;
}
**********************************************************CODE O(6*N)********************************************************
//Coder: Balajiganapathi
#ifndef ONLINE_JUDGE
# define DEBUG
# define TRACE
#else
//# define NDEBUG
#endif
#include <algorithm>
const int mx = 100005;
const long long oo = 1000000000000000000ll;
char col[mx];
char o[] = "rgb";
int n;
int main() {
int t;
scanf("%d", &t);
while(t--) {
scanf("%s", col);
n = strlen(col);
long long ans = oo;
sort(o, o + 3);
do {
long long cur = 0;
int c0 = 0, c1 = 0, c2 = 0;
for(int i = 0; i < n; ++i) {
if(col[i] == o[0]) {
++c0;
cur += c1 + c2;
} else if(col[i] == o[1]) {
++c1;
cur += c2;
} else if(col[i] == o[2]) {
++c2;
}
}
ans = min(ans, cur);
} while(next_permutation(o, o + 3));
printf("%lld\n", ans);
}
return 0;
}