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++ (GCC 9.2.1) (judge verdict: Accepted)

#include "bits/stdc++.h"
#include <boost/range/irange.hpp>
using namespace std;
using boost::irange;

// 定義
typedef long long           ll;
typedef pair<ll, ll>        P;
#define ALL(x)              (x).begin(),(x).end()
#define REP(i, n)           for (ll i = 0 ; i < (ll)n ; ++i)
#define REPN(i, m, n)       for (ll i = m ; i < (ll)n ; ++i)
const ll                    INF = 2e9;
const ll                    INF_LL = 1LL<<60;
const ll                    MOD = 998244353;

ll Ceil(ll val, ll div)   { return (val + div - 1) / div; }
ll CeilN(ll val, ll div)  { return Ceil(val, div) * div; }
ll FloorN(ll x, ll n)     { return (x - x % n); }
bool IsOdd(ll x)          { return ((x & 1) == 1); }
bool IsEven(ll x)         { return ((x & 1) == 0); }
template<class T> bool chmax(T& a, T b) { if (a < b) { a = b; return 1; } return 0; }
template<class T> bool chmin(T& a, T b) { if (a > b) { a = b; return 1; } return 0; }

template<class T>
class Ruiseki
{
private:
	int num;

public:
	vector<T> sumVal;
	Ruiseki(const vector<T> &srcVal)
	{
		num = srcVal.size();
		sumVal.resize(num + 1, 0);
		for (int i = 0; i < num; i++) {
			sumVal[i + 1] = sumVal[i] + srcVal[i];
		}
	}

	T GetSumAll()
	{
		return sumVal[num];
	}

	T GetSumRange(int startIdx, int stopIdx)
	{
		return sumVal[stopIdx] - sumVal[startIdx];
	}

	T GetSumFromTop(int stopIdx)
	{
		return sumVal[stopIdx] - sumVal[0];
	}

	T GetSumFromEnd(int startIdx)
	{
		return sumVal[num] - sumVal[startIdx];
	}
};

// 処理
void Solve()
{
	ll N;
	string S;
	cin >> N >> S;
	vector<ll> b(N);
	vector<ll> w(N);
	REP(i, N) {
		b[i] = S[i] == '#';
		w[i] = S[i] == '.';
	}

	ll ans = INF;
	Ruiseki<ll> ruib(b);
	Ruiseki<ll> ruiw(w);
	REP(i, N + 1) {
		ll ansOne = ruib.GetSumFromTop(i) + ruiw.GetSumFromEnd(i);
		chmin(ans, ansOne);
	}

	cout << ans << endl;
}

// メイン
int main()
{
	cin.tie(nullptr);
	ios_base::sync_with_stdio(false);
	cout << fixed << setprecision(15);
	Solve();
	return 0;
}