题目
题解思路
坑点
map的count只返回0或者1,不返回权值。
很容易想到用前缀和,枚举每个能等于总和1/3的总前缀和(sum)(只有这些才有可能切出3块)。找到在尾部之前是否存在1/2sum的前缀和。
如果存在就可以拼接出答案,但是,可能存在不止一个这样的值。这样我们好像只能往后搜查出答案,但是这样是有可能超时的。
想了一会,想到了一个在线map的方法。
我们存一个map来保存i到i之后的每个前缀和值的个数。
这样我们只需直接mp[sum*2]]就能找到后面有几个数可以划分出。
当我们处理完这个数后,就把这个数在map里的个数减去,防止影响后面的情况。
但是有一个特例,就是sum为0的情况。
我们特判了首和尾即可-2。
这个方法有点巧妙,是自己独立想出来的。
AC代码
#include <bits/stdc++.h>
using namespace std;
int a[100010] ;
long long sum[100010] ;
int main ()
{
unordered_map < long long , int > mp ;
int n ;
cin >> n ;
for ( int i = 1 ; i <= n ; i++ )
{
cin >> a[i] ;
sum[i] = sum[i-1] + a[i] ;
mp[ sum[i] ] ++ ;
}
long long ans = 0 ;
for ( int i = 1 ; i <= n-2 ; i++ )
{
if ( 3*sum[i] == sum[n] )
{
if ( sum[i] == 0 )
{
if ( mp[0] > 2 )
ans += mp[0] - 2 ;
}else if ( mp.count(2*sum[i]) )
{
ans += mp[2*sum[i]] ;
}
}
mp[sum[i]]-- ;
}
cout << ans << "\n" ;
return 0 ;
}