#include<bits/stdc++.h>
using namespace std;
#include <ext/pb_ds/assoc_container.hpp> 
#include <ext/pb_ds/tree_policy.hpp> 
using namespace __gnu_pbds;
// #pragma GCC optimize("O2")
typedef long long int ll;
typedef long double ld;
typedef map <ll,ll> mm;
typedef vector <ll> mv;
typedef pair <ll,ll> mp;
typedef set <ll> ms;
typedef multiset <ll> mms;
typedef queue <ll> mq;
typedef deque <ll> mdq;
typedef stack <ll> mst;
typedef priority_queue <ll> mpq;
typedef priority_queue <ll, vector<ll>, greater<ll> > mmh;
typedef complex<double> cd;
#define ordered_set tree<ll, null_type,less<ll>, rb_tree_tag,tree_order_statistics_node_update>
#define ordered_multiset tree<ll,null_type,less_equal<ll>,rb_tree_tag,tree_order_statistics_node_update>
#define fastio ios_base::sync_with_stdio(0); cin.tie(0); cout.tie(0);
#define flush cout.flush();
#define all(v) v.begin(),v.end()
#define deb(x) cout << #x << " " << x << endl;
#define ff first
#define ss second
#define pb(v) push_back(v)
#define lb(v) lower_bound(v)
#define ub(v) upper_bound(v)
#define cn continue
#define forl(i,n) for(ll i=0;i<n;i++)
#define forlr(i,n) for(ll i=n-1;i>=0;i--)
#define rev(s) reverse(s.begin(),s.end())
void swap(ll &a,ll &b) {
	ll tmp=a;
	a=b;
	b=tmp;
}
ll atoistring(string s) {
	stringstream lol(s);
	ll x;
	lol>>x;
	return x;
}
void pv(mv v) {
	forl(i,v.size()) cout<<v[i]<<" ";
	cout<<"\n";
}
void pa(ll *v, ll size) {
	forl(i,size) cout<<v[i]<<" ";
	cout<<"\n";
}
void removeDups(mv &v) {
	sort(all(v));
	mv::iterator it = unique(v.begin(), v.end());
	v.resize(distance(v.begin(), it));
}
inline ld kthRoot(ld n, ll k) {
	return pow(k, (1.0 / k) * (log(n) / log(k)));
}
ll power(ll x, ll y, ll p) {
	ll res=1;
	x=x%p;
	while(y>0) {
		if(y&1) res = (res*x)%p;
		y=y>>1;
		x=(x*x)%p;
	}
	return res;
}
void checkmod(ll &x, ll mod) {
	if(x>=mod) x%=mod;
}

ll mod = 1e9 + 7;

ll arr[200005], pre[200005], maxi[200005];
void thisIsMain() {
	ll n;
	cin>>n;
	forl(i,n) {
		cin>>arr[i];
		pre[i] = arr[i];
	}
	maxi[0] = arr[0];
	forl(i,n - 1) {
		pre[i + 1] += pre[i];
		maxi[i + 1] = max(maxi[i], pre[i + 1]);
	}
	ll ans = 0;
	ll pos = 0;
	forl(i,n) {
		ans = max(ans, pos + maxi[i]);
		pos += pre[i];
	}
	cout<<ans<<"\n";
}

int main(void)
{
	fastio
	ll t = 1;
	// cin>>t;
	while(t--) thisIsMain();
	return 0;
}
#include<iostream>
#include<math.h>
#include<algorithm>
#include<stdint.h>
#include<vector>
#include<deque>
#include<stack>
#include<functional>
#include<string>
#include<numeric>
#include<cstring>
#include<random>
#include<array>
#include<fstream>
#include<iomanip>
#include<list>
#include<set>
#include<map>
#include<unordered_map>
#include<unordered_set>
#include<bitset>
#include<queue>

/*
#include<boost/multiprecision/cpp_int.hpp>
using namespace boost::multiprecision;
*/

using namespace std;

using ll = long long;
using ull = unsigned long long;

#define REP(i,a,b) for(ll i = a; i < b; ++i)
#define PRI(s) std::cout << s << endl
#define PRIF(v, n) printf("%."#n"f\n", (double)v)

template<typename A, typename B>void mins(A& a, const B& b) { a = min(a, (A)b); };
template<typename A, typename B>void maxs(A& a, const B& b) { a = max(a, (A)b); };


vector<vector<bool>> S;
vector<vector<vector<pair<int,int>>>> E;
vector<vector<int>> F;

void dfs(int i, int j, int c) {
	F[i][j] = c;
	for (auto p : E[i][j]) if(F[p.first][p.second]==-1)dfs(p.first, p.second, c);
}

int main() {
	ll H, W; cin >> H >> W;
	S.resize(H, vector<bool>(W));
	E.resize(H, vector<vector<pair<int, int>>>(W));
	F.resize(H, vector<int>(W, -1));

	REP(i, 0, H) REP(j, 0, W) {
		char c; cin >> c;
		S[i][j] = (c == '#');
	}
	S[0][0] = true;
	S[0][W - 1] = true;
	S[H - 1][0] = true;
	S[H - 1][W - 1] = true;
	
	REP(i, 0, H) {
		int last = -1;
		REP(j, 0, W) {
			if (!S[i][j]) continue;
			if (last == -1) {
				last = j;
				continue;
			}

			E[i][j].push_back({ i,last });
			E[i][last].push_back({ i,j });
			last = j;
		}
	}

	REP(j, 0, W) {
		int last = -1;
		REP(i, 0, H) {
			if (!S[i][j]) continue;
			if (last == -1) {
				last = i;
				continue;
			}

			E[i][j].push_back({ last,j });
			E[last][j].push_back({ i,j });
			last = i;
		}
	}

	int fm = -1;
	REP(i, 0, H) REP(j, 0, W) {
		if (!S[i][j] || F[i][j] != -1)continue;
		dfs(i, j, ++fm);
	}

	int emptycol = 0;
	int emptyrow = 0;
	REP(i, 0, H) {
		bool ok = true;
		REP(j, 0, W) {
			if (S[i][j]) {
				ok = false;
				break;
			}
		}
		if (ok)++emptycol;
	}
	REP(j, 0, W) {
		bool ok = true;
		REP(i, 0, H) {
			if (S[i][j]) {
				ok = false;
				break;
			}
		}
		if (ok)++emptyrow;
	}

	PRI(fm + min(emptycol, emptyrow));

	return 0;
}
