//#define NDEBUG
#define _CRT_SECURE_NO_WARNINGS
#include <array>
#include <cstddef>
#include <cstdint>
#include <cstdio>
#include <limits>
#include <memory>
#include <string>
#include <type_traits>

class rep {
	const ::std::size_t f, l;

public:
	using value_type = ::std::size_t;
	using reference = value_type;
	class repitr {
		friend rep;
		value_type i;
		repitr(value_type x) noexcept : i(x) {}

	public:
		void operator++() noexcept { ++i; }
		reference operator*() const noexcept { return i; }
		bool operator!=(const repitr x) const noexcept { return i != x.i; }
	};
	explicit rep(value_type first, value_type last) noexcept
		: f(first), l(last) {}
	repitr begin() const noexcept { return repitr(f); }
	repitr end() const noexcept { return repitr(l); }
};
class Rrep {
	const ::std::size_t f, l;

public:
	using value_type = ::std::size_t;
	using reference = value_type;
	class Rrepitr {
		friend Rrep;
		value_type i;
		Rrepitr(value_type x) noexcept : i(x) {}

	public:
		void operator++() noexcept { --i; }
		reference operator*() const noexcept { return i - 1; }
		bool operator!=(const Rrepitr x) const noexcept { return i != x.i; }
	};
	explicit Rrep(value_type first, value_type last) noexcept
		: f(first), l(last) {}
	Rrepitr begin() const noexcept { return Rrepitr(l); }
	Rrepitr end() const noexcept { return Rrepitr(f); }
};
template <class T> bool maxi(T &a, const T &b) {
	if (b < a)
		return 0;
	a = b;
	return 1;
}
template <class T> bool mini(T &a, const T &b) {
	if (a < b)
		return 0;
	a = b;
	return 1;
}
template <class T> bool smaxi(T &a, const T &b) {
	if (a < b) {
		a = b;
		return 1;
	}
	return 0;
}
template <class T> bool smini(T &a, const T &b) {
	if (b < a) {
		a = b;
		return 1;
	}
	return 0;
}
class customIO {
	int c;
	bool f;
	::std::array<int, 30> buf;
	void get_c() { c = fgetc(stdin); }
	void put_c(int x) { fputc(x, stdout); }
	bool vacant() { return c == ' ' || c == '\n'; }

	// in

	void cueing() {
		while (get_c(), vacant())
			;
	}

public:
	template <class T>
	auto operator>>(T &d) ->
		typename ::std::enable_if<::std::is_signed<T>::value, customIO &>::type {
		d = 0;
		f = 0;
		cueing();
		if (c == '-')
			f = 1, get_c();
		do
			d = d * 10 + c - '0';
		while (get_c(), !vacant());
		if (f)
			d = -d;
		return *this;
	}
	template <class T>
	auto operator>>(T &d) ->
		typename ::std::enable_if<!::std::is_signed<T>::value, customIO &>::type {
		d = 0;
		cueing();
		do
			d = d * 10 + c - '0';
		while (get_c(), !vacant());
		return *this;
	}
	customIO &operator>>(char &d) {
		cueing();
		d = c;
		return *this;
	}
	customIO &operator>>(double &d) {
		scanf("%lf", &d);
		return *this;
	}
	customIO &operator>>(::std::string &d) {
		d.clear();
		cueing();
		do
			d.push_back(c);
		while (get_c(), !vacant());
		return *this;
	}

	// out

	template <class T>
	auto operator<<(T d) ->
		typename ::std::enable_if<::std::is_signed<T>::value, customIO &>::type {
		c = 0;
		f = 0;
		if (d < static_cast<T>(0))
			f = 1, d = -d;
		while (d)
			buf[c++] = d % 10 + '0', d /= 10;
		if (!c)
			buf[c++] = '0';
		if (f)
			put_c('-');
		while (c--)
			put_c(buf[c]);
		return *this;
	}
	template <class T>
	auto operator<<(T d) ->
		typename ::std::enable_if<!::std::is_signed<T>::value, customIO &>::type {
		c = 0;
		while (d)
			buf[c++] = d % 10 + '0', d /= 10;
		if (!c)
			buf[c++] = '0';
		while (c--)
			put_c(buf[c]);
		return *this;
	}
	customIO &operator<<(char d) {
		put_c(d);
		return *this;
	}
	customIO &operator<<(const ::std::string &d) {
		for (const auto e : d)
			put_c(e);
		return *this;
	}
	customIO &operator<<(const char *d) {
		while (*d != '\0')
			put_c(*(d++));
		return *this;
	}
	customIO &operator<<(double d) {
		/*
		printf("%1.9f",d);
		/*/
		printf("%f", d);
		//*/
		return *this;
	}
	void endl() { put_c('\n'); }
	void space() { put_c(' '); }
	operator int() { return 0; }
} IO;
template <class T = ::std::size_t> T scan() {
	T ret;
	IO >> ret;
	return ret;
}
#include <algorithm>
#include <array>
#include <cassert>
#include <cstddef>
#include <cstdint>
#include <limits>
#include <utility>
#include <vector>

#ifdef __has_builtin
::std::size_t popcount64(::std::uint_fast64_t c) {
	return __builtin_popcountll(c);
}
#else
::std::size_t popcount64(::std::uint_fast64_t c) {
	c = (c & 0x5555555555555555) + ((c & 0xAAAAAAAAAAAAAAAA) >> 1);
	c = (c & 0x3333333333333333) + ((c & 0xCCCCCCCCCCCCCCCC) >> 2);
	return static_cast<::std::size_t>(
		((c + (c >> 4)) & 0x0F0F0F0F0F0F0F0F) * 0x0101010101010101 >> 56 & 0x7f);
}
#endif

template <typename Integral,
	::std::size_t bitsize = ::std::numeric_limits<Integral>::digits()>
	class wavelet_matrix {
	public:
		using value_type = Integral;
		using size_type = ::std::size_t;

	private:
		using uint64 = ::std::uint_fast64_t;
		struct bitvector {
			::std::vector<::std::pair<uint64, size_type>> dic;
			size_type cnt;
			value_type bit;
			bitvector() {}
			bitvector(const size_type bsize) : dic(bsize, { 0, 0 }) {}
			void set(const size_type index) {
				dic[index >> 6].first |= static_cast<uint64>(1) << (index & 0x3f);
			}
			void build() {
				const size_type len = dic.size();
				for (size_type i = 1; i < len; ++i)
					dic[i].second = dic[i - 1].second + popcount64(dic[i - 1].first);
			}
			size_type rank(const size_type last) const {
				return dic[last >> 6].second +
					popcount64(dic[last >> 6].first &
					(static_cast<uint64>(1) << (last & 0x3f)) - 1);
			}
			bool access(const size_type index) const {
				return dic[index >> 6].first >> (index & 0x3f) & 1;
			}
		};
		::std::array<bitvector, bitsize> matrix_;
		value_type not_found_;
		size_type size_;

	public:
		wavelet_matrix() : matrix_(), size_(0), not_found_(0) {}
		template <class InputIter>
		wavelet_matrix(InputIter first, InputIter last,
			const value_type not_found = 0)
			: size_(0), not_found_(not_found) {
			::std::vector<value_type> vec0(first, last);
			size_ = vec0.size();
			const size_type len = size_, block = (len >> 5) + 1;
			::std::vector<value_type> vec_l(len), vec_r(len);
			size_type l, r;
			value_type temp = static_cast<value_type>(1) << (bitsize - 1);
			for (auto &v : matrix_) {
				v = bitvector(block);
				v.bit = temp;
				temp = temp >> 1 & ~temp;
				l = 0;
				r = 0;
				for (size_type j = 0; j < len; ++j)
					if (vec0[j] & v.bit)
						vec_r[r++] = vec0[j], v.set(j);
					else
						vec_l[l++] = vec0[j];
				v.cnt = l;
				v.build();
				::std::swap(vec0, vec_l);
				::std::copy(vec_r.begin(), vec_r.begin() + r, vec0.begin() + l);
			}
		}

		size_type size() const noexcept { return size_; }
		bool empty() const noexcept { return size() == 0; }

		value_type access(size_type index) const {
			assert(index < size());
			value_type ret = 0;
			for (const auto &v : matrix_)
				if (v.access(index))
					ret |= v.bit, index = v.rank(index) + v.cnt;
				else
					index -= v.rank(index);
			return ret;
		}
		value_type operator[](const size_type index) const {
			assert(index < size());
			return access(index);
		}
		size_type rank(size_type first, size_type last, const value_type x) const {
			assert(first <= size());
			assert(last <= size());
			assert(first <= last);
			for (const auto &v : matrix_)
				if (x & v.bit)
					first = v.rank(first) + v.cnt, last = v.rank(last) + v.cnt;
				else
					first -= v.rank(first), last -= v.rank(last);
			return last - first;
		}
		value_type quantile(size_type first, size_type last, size_type k) const {
			assert(first < size());
			assert(last <= size());
			assert(first < last);
			assert(last - first > k);
			value_type ret = 0;
			for (const auto &v : matrix_) {
				const size_type l = v.rank(first), r = v.rank(last);
				if (r - l > k)
					first = l + v.cnt, last = r + v.cnt, ret |= v.bit;
				else
					first -= l, last -= r, k -= r - l;
			}
			return ret;
		}
		value_type rquantile(size_type first, size_type last, size_type k) const {
			assert(first < size());
			assert(last <= size());
			assert(first < last);
			assert(last - first > k);
			return quantile(first, last, last - first - k - 1);
		}
		size_type less_than(size_type first, size_type last,
			const value_type x) const {
			assert(first <= size());
			assert(last <= size());
			assert(first <= last);
			size_type ret = 0;
			for (const auto &v : matrix_) {
				if (x & v.bit) {
					ret += last - first + v.rank(first) - v.rank(last);
					first = v.rank(first) + v.cnt;
					last = v.rank(last) + v.cnt;
				}
				else {
					first -= v.rank(first);
					last -= v.rank(last);
				}
			}
			return ret;
		}
		size_type at_least(size_type first, size_type last,
			const value_type x) const {
			assert(first <= size());
			assert(last <= size());
			assert(first <= last);
			size_type ret = 0;
			for (const auto &v : matrix_) {
				if (x & v.bit) {
					first = v.rank(first) + v.cnt;
					last = v.rank(last) + v.cnt;
				}
				else {
					ret += v.rank(last) - v.rank(first);
					first -= v.rank(first);
					last -= v.rank(last);
				}
			}
			return ret + (last - first);
		}
		size_type greater_than(size_type first, size_type last,
			const value_type x) const {
			assert(first <= size());
			assert(last <= size());
			assert(first <= last);
			size_type ret = 0;
			for (const auto &v : matrix_) {
				if (x & v.bit) {
					first = v.rank(first) + v.cnt;
					last = v.rank(last) + v.cnt;
				}
				else {
					ret += v.rank(last) - v.rank(first);
					first -= v.rank(first);
					last -= v.rank(last);
				}
			}
			return ret;
		}
		size_type at_most(size_type first, size_type last, const value_type x) const {
			assert(first <= size());
			assert(last <= size());
			assert(first <= last);
			size_type ret = 0;
			for (const auto &v : matrix_) {
				if (x & v.bit) {
					ret += last - first + v.rank(first) - v.rank(last);
					first = v.rank(first) + v.cnt;
					last = v.rank(last) + v.cnt;
				}
				else {
					first -= v.rank(first);
					last -= v.rank(last);
				}
			}
			return ret + (last - first);
		}
		size_type rangefreq(size_type first, size_type last, const value_type lower,
			const value_type upper) const {
			assert(first <= size());
			assert(last <= size());
			assert(first <= last);
			assert(lower <= upper);
			return at_least(first, last, lower) - at_least(first, last, upper);
		}
		value_type successor(const size_type first, const size_type last,
			const value_type x) const {
			assert(first <= size());
			assert(last <= size());
			assert(first <= last);
			const size_type k = at_least(first, last, x);
			return k ? quantile(first, last, k - 1) : not_found_;
		}
		value_type predecessor(const size_type first, const size_type last,
			const value_type x) const {
			assert(first <= size());
			assert(last <= size());
			assert(first <= last);
			const size_type k = greater_than(first, last, x);
			return last - first == k ? not_found_ : quantile(first, last, k);
		}
		value_type strict_succ(const size_type first, const size_type last,
			const value_type x) const {
			assert(first <= size());
			assert(last <= size());
			assert(first <= last);
			const size_type k = greater_than(first, last, x);
			return k ? quantile(first, last, k - 1) : not_found_;
		}
		value_type strict_pred(const size_type first, const size_type last,
			const value_type x) const {
			assert(first <= size());
			assert(last <= size());
			assert(first <= last);
			const size_type k = at_least(first, last, x);
			return last - first == k ? not_found_ : quantile(first, last, k);
		}
};

using int32 = ::std::int_fast32_t;
using int64 = ::std::int_fast64_t;
using uint32 = ::std::uint_fast32_t;
using uint64 = ::std::uint_fast64_t;
using intl32 = ::std::int_least32_t;
using intl64 = ::std::int_least64_t;
using uintl32 = ::std::uint_least32_t;
using uintl64 = ::std::uint_least64_t;

#include <algorithm>
#include <utility>
#include <vector>
#include<limits>
#include<array>

int main() {
	constexpr uint64 NOT = ::std::numeric_limits<uint64>::max();
	const uint32 n = scan();
	::std::vector<uint64> a(n);
	for (auto &e : a)
		IO >> e;
	::std::vector<uint64> l(n+1), r(n+1);
	for (const auto i : rep(0, n))
		l[i + 1] = l[i] + a[i];
	for (const auto i : rep(0, n))
		r[i + 1] = r[i] + a[n - i - 1];
	wavelet_matrix<uint64, 50> lw(l.cbegin(), l.cend(),NOT);
	wavelet_matrix<uint64, 50> rw(r.cbegin(), r.cend(), NOT);
	uint64 ans = ::std::numeric_limits<uint64>::max();
	::std::array<uint64, 4> p;
	for (const auto i : rep(2, n - 1)) {
		uint64 lbase = l[i];
		uint64 ls = lw.successor(1, i, lbase / 2);
		uint64 lp = lw.predecessor(1, i, lbase / 2);
		if (ls == NOT)p[0] = lp;
		else if (lp == NOT)p[0] = ls;
		else p[0] = ::std::max(lp, lbase - ls);
		p[1] = lbase - p[0];
		const ::std::size_t j = n - i;
		uint64 rbase = r[j];
		uint64 rs = rw.successor(1, j, rbase / 2);
		uint64 rp = rw.predecessor(1, j, rbase / 2);
		if (rs == NOT) p[2] = rp;
		else if (rp == NOT) p[2] = rs;
		else p[2] = ::std::max(rp, rbase - rs);
		p[3] = rbase - p[2];
		::std::sort(p.begin(), p.end());
		smini(ans, p[3] - p[0]);
	}
	IO << ans << '\n';
	return 0;
}

Measured memory_bytes: 21420