Problem:
Score : 300 points

Problem Statement

There are N stones arranged in a row. Every stone is painted white or black.
A string S represents the color of the stones. The i-th stone from the left is white if the i-th character of S is ., and the stone is black if the character is #.

Takahashi wants to change the colors of some stones to black or white so that there will be no white stone immediately to the right of a black stone.
Find the minimum number of stones that needs to be recolored.

Constraints

1 \leq N \leq 2\times 10^5

S is a string of length N consisting of . and #.

Input

Input is given from Standard Input in the following format:

N
S

Output

Print the minimum number of stones that needs to be recolored.

Sample Input 1

3
#.#

Sample Output 1

1

It is enough to change the color of the first stone to white.

Sample Input 2

5
#.##.

Sample Output 2

2

Sample Input 3

9
.........

Sample Output 3

0

Solution in C# (Mono 4.6.2.0) (judge verdict: Time Limit Exceeded)

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using BitArray = System.Collections.BitArray;
using BigInteger = System.Numerics.BigInteger;

namespace AtCoderProject
{
    class Stones
    {
        public bool type;
        public int count;
    }
    class Program
    {
        static void Main()
        {
            Console.WriteLine(new Program().Calc());
        }

        public object Calc()
        {
            ReadLine();
            var stones = ReadLine().Select(c => c == '.').ToArray();
            var stonesGroup = new List<Stones>();

            bool type = stones[0];
            int s_index = 0;
            for (int i = 1; i < stones.Length; i++)
            {
                if (stones[i] != type)
                {
                    stonesGroup.Add(new Stones { count = i - s_index, type = type });
                    type = stones[i];
                    s_index = i;
                }
            }
            stonesGroup.Add(new Stones { count = stones.Length - s_index, type = type });
            return Calc(stonesGroup);
        }

        object Calc(List<Stones> stonesGroup)
        {
            int res = 0;
            Calc(stonesGroup, ref res);
            return res;
        }
        void Calc(List<Stones> stonesGroup, ref int res)
        {
            if (stonesGroup.Count <= 1) return;

            var firstGroup = stonesGroup[0];
            var lastGroup = stonesGroup[stonesGroup.Count - 1];


            if (stonesGroup.Count == 2)
            {
                if (lastGroup.type)
                    res += Math.Min(firstGroup.count, lastGroup.count);
                return;
            }

            if (!lastGroup.type)
                stonesGroup.RemoveAt(stonesGroup.Count - 1);
            if (firstGroup.type)
                stonesGroup.RemoveAt(0);

            if (firstGroup.count <= lastGroup.count)
            {
                stonesGroup.RemoveAt(0);
                stonesGroup[0].count += firstGroup.count;
                res += firstGroup.count;
            }
            else
            {
                stonesGroup.RemoveAt(stonesGroup.Count - 1);
                stonesGroup[stonesGroup.Count - 1].count += lastGroup.count;
                res += lastGroup.count;
            }

            Calc(stonesGroup, ref res);

            return;
        }

#if DEBUG
#pragma warning disable IDE0051 // 使用されていないプライベート メンバーを削除する
#pragma warning disable IDE1006 // 命名スタイル
        static string _ReadLineImpl() => queue.Dequeue();
#pragma warning restore IDE1006 // 命名スタイル
        static readonly Queue<string> queue;
        static Program()
        {
            string input = @"
5

";
            queue = new Queue<string>();
            foreach (var line in input.Split(new char[] { '\r', '\n' }, StringSplitOptions.RemoveEmptyEntries))
                queue.Enqueue(line);
        }
#else
        private static string _ReadLineImpl() => Console.ReadLine();
#endif
        static string ReadLine() => _ReadLineImpl();
        static int ReadLineInt32() => int.Parse(ReadLine());
        static long ReadLineInt64() => long.Parse(ReadLine());
        static ulong ReadLineUInt64() => ulong.Parse(ReadLine());
        static double ReadLineDouble() => double.Parse(ReadLine());
        static List<string> ReadLineSplit() => ReadLine().Split().ToList();
        static List<int> ReadLineSplitInt32() => ReadLine().Split().Select(s => int.Parse(s)).ToList();
        static List<long> ReadLineSplitInt64() => ReadLine().Split().Select(s => long.Parse(s)).ToList();
        static List<ulong> ReadLineSplitUInt64() => ReadLine().Split().Select(s => ulong.Parse(s)).ToList();
        static List<double> ReadLineSplitDouble() => ReadLine().Split().Select(s => double.Parse(s)).ToList();

        static IEnumerable<string> RepeatReadLines(int count)
        {
            for (int i = 0; i < count; i++)
                yield return ReadLine();
        }
        static IEnumerable<int> RepeatReadLinesInt32(int count)
        {
            for (int i = 0; i < count; i++)
                yield return ReadLineInt32();
        }
        static IEnumerable<List<string>> RepeatReadLinesSplit(int count)
        {
            for (int i = 0; i < count; i++)
                yield return ReadLineSplit();
        }
    }
    static class BitArrayUtils
    {
        static BitArray ToBitArray(this long l)
        {
            return new BitArray(BitConverter.GetBytes(l));
        }
        static long ToInt64(this BitArray bitArray)
        {
            var array = new byte[8];
            bitArray.CopyTo(array, 0);
            return BitConverter.ToInt64(array, 0);
        }
        static BitArray ToBitArray(this ulong l)
        {
            return new BitArray(BitConverter.GetBytes(l));
        }
        static ulong ToUInt64(this BitArray bitArray)
        {
            var array = new byte[8];
            bitArray.CopyTo(array, 0);
            return BitConverter.ToUInt64(array, 0);
        }
    }
}