#include <iostream>
#include <vector>
using namespace std;
int main() {
int n;
cin >> n;
vector<long long> a(n);
for (int i = 0; i < n; ++i) cin >> a[i];
long long total = 0;
for (auto val : a) total += val;
if (total % 3 != 0) {
cout << 0 << endl;
return 0;
}
long long target = total / 3;
vector<long long> prefix(n);
prefix[0] = a[0];
for (int i = 1; i < n; ++i) prefix[i] = prefix[i - 1] + a[i];
// 正数前缀和数组:pos_count[i] 表示 [0..i] 中有多少个正数
vector<int> pos_count(n);
pos_count[0] = a[0] > 0 ? 1 : 0;
for (int i = 1; i < n; ++i) {
pos_count[i] = pos_count[i - 1] + (a[i] > 0 ? 1 : 0);
}
// 后缀正数存在判断
vector<bool> has_pos_suffix(n);
has_pos_suffix[n - 1] = a[n - 1] > 0;
for (int i = n - 2; i >= 0; --i) {
has_pos_suffix[i] = has_pos_suffix[i + 1] || (a[i] > 0);
}
// 每个前缀和为 target 的合法切点数(且该段含正数)
vector<int> valid_cut_count(n, 0);
int count = 0;
for (int i = 0; i < n - 2; ++i) {
if (prefix[i] == target && pos_count[i] > 0) {
count++;
}
valid_cut_count[i] = count;
}
long long ans = 0;
for (int i = 1; i < n - 1; ++i) {
if (prefix[i] == 2 * target && has_pos_suffix[i + 1]) {
// 要判断第二段是否有正数:[j+1 .. i] -> [0..i] - [0..j]
// 我们从前面记录的 valid_cut_count[i-1] 是所有合法 j <= i-1
// 现在我们只要排除那些 j 的切法中 j+1..i 没有正数的就行了
// 枚举所有 prefix[j] == target 且 j < i
// 因为我们不能再 O(n) 枚举了,我们估算第二段含正数的条件:
// 当前位置 i,前缀正数个数:pos_count[i]
// 合法第一段结尾 j 的位置数量:valid_cut_count[i - 1]
// 为了保证第二段 [j+1..i] 有正数:
// 对于每一个 j 满足 prefix[j] == target 且 pos_count[i] - pos_count[j] > 0
// 用滑动窗口(双指针可进一步优化)
// 简化处理:暴力尝试每个合法 j,直到 i(只考虑 prefix[j] == target 且段含正数)
for (int j = 0; j < i; ++j) {
if (prefix[j] == target && pos_count[j] > 0) {
// 判断 [j+1..i] 是否含正数
int pos_in_segment = pos_count[i] - pos_count[j];
if (pos_in_segment > 0) {
ans++;
}
}
}
}
}
cout << ans << endl;
return 0;
}