Let’s consider the prefix sum array s = [ a 1 , a 1 + a 2 , … , a 1 + a 2 + … + a n ] s=[a_1,a_1+a_2,\ldots,a_1+a_2+\ldots+a_n] s=[a1,a1+a2,…,a1+a2+…+an].
For every index i i i such that a i = 0 a_i=0 ai=0, if we change the value of a i a_i ai to x x x, then every element from the suffix [ s i , s i + 1 , … , s n ] [s_i,s_{i+1},\ldots,s_n] [si,si+1,…,sn] will be increased by x x x. Therefore, if a i 1 = a i 2 = … = a i k = 0 a_{i_1}=a_{i_2}=\ldots=a_{i_k}=0 ai1=ai2=…=aik=0, we’ll partition array s s s into multiple subarrays:
For each of the other subarrays [ s l , s l + 1 , … , s r ] [s_l,s_{l+1},\ldots,s_r] [sl,sl+1,…,sr], let x x x be the most frequent element in the subarray, appearing f r [ x ] fr[x] fr[x] times. Since a l = 0 a_l=0 al=0, we can change the value of a l a_l al to − x -x −x. In this case, every x x x in this subarray will become equal to 0 0 0, and our current subarray will contribute with f r [ x ] fr[x] fr[x] towards the final answer.
Time complexity per testcase: O ( N l o g N ) O(NlogN) O(NlogN)
#include
using namespace std;
typedef long long LL;
int main()
{
int T;cin>>T;
while(T--)
{
int n;cin>>n;
map<LL,LL> b;
bool ok_zero=false;
LL sum=0,mx=0,res=0;
for(int i=0;i<n;i++)
{
int x;cin>>x;
if(x==0)
{
if(ok_zero) res+=mx;
else res+=b[0];
ok_zero=true;
mx=0;
b.clear();
}
sum+=x;
b[sum]++;
mx=max(mx,b[sum]);
}
if(ok_zero) res+=mx;
else res+=b[0];
cout<<res<<endl;
}
return 0;
}