cppAcademy
FROM LEARNING TO COMPETING

Proficient.
Put your skills to the test.

Bulgarian Informatics Group B · 2007–2026

274 independently explained problems: 54 Municipal, 54 Regional, 109 National Olympiad and 57 Autumn Tournament tasks. Difficulty labels are learning estimates, not official ratings. Some events share Junior/IATI or Group A/B problem sets. Special formats, scoring limitations and source clarifications are explained on affected tasks. The two previously featured Autumn problems keep their existing permanent URLs.
GROUP B2011 · MediumSorting and two pointers

Count Unordered Zero-Sum Teams

Autumn Tournament (2011)

Submission name: zerosum.cpp

Problem summary

Count unordered triples of different participant indices whose three integer values sum to zero. Participants remain distinct when their values are equal.

Input

N, followed by N integer values.

Output

The number of zero-sum triples.

Constraints

1 ≤ N ≤ 10000; −10000 ≤ each value ≤ 10000.

Worked example

Original statement sample.

Input

10
2 -5 2 3 -4 7 -4 0 1 -6

Output

6

Solution analysis

  1. Sort the values. Fix the smallest index i of a triple, then search for two later values with sum −a[i]. Start one pointer at i+1 and the other at N−1. A too-small sum requires increasing the left value; a too-large sum requires decreasing the right value.
  2. When the sum is zero and the endpoint values differ, count their equal-value runs. Every left-run participant can pair with every right-run participant, contributing leftCount·rightCount. Skip both complete runs afterwards. If the endpoint values are equal, all remaining positions have that value: add c(c−1)/2 and finish this i.
  3. The sample has two different participants of value 2 and two of value −4. Thus the value pattern (2,2,−4) gives two teams, while (3,−4,1) also gives two. Together with the two choices of participant 2 in (−5,2,3), the answer is 6.
  4. Do not skip duplicate fixed values: each fixed index represents a different participant. Use long long for the answer, since even the all-zero case has C(N,3) teams.

Why it works

For a fixed i, sorted order makes each pointer move discard only pairs that cannot meet the target. At a successful sum, run multiplication counts every index pair with those endpoint values exactly once. Every triple has one unique smallest sorted index i, so summing these counts gives precisely all unordered teams.

Complexity: O(N²) time and O(N) input storage. Sorting is O(N log N), and for each fixed i the two pointers collectively move at most N positions. The answer uses 64-bit arithmetic.

Watch out. Do not count only distinct value triples. Do not skip repeated fixed indices. Handle equal left/right values with a binomial count rather than run multiplication, and count only indices i<left<right.

Commented C++17 solution

An independently written complete program with standard headers.

#include<algorithm>
#include<iostream>
#include<vector>
using namespace std;
int main(){
    int n;
    cin>>n;
    vector<int>values(n);
    for(int&value:values){
        cin>>value;
    }
    sort(values.begin(),values.end());
    long long answer=0;
    for(int i=0;i<n;i++){
        int left=i+1;
        int right=n-1;
        while(left<right){
            int sum=values[i]+values[left]+values[right];
            if(sum<0){
                left++;
            }
            else if(sum>0){
                right--;
            }
            else if(values[left]==values[right]){
                long long count=right-left+1;
                answer+=count*(count-1)/2;
                break;
            }
            else{
                int leftValue=values[left];
                int rightValue=values[right];
                long long leftCount=0;
                long long rightCount=0;
                while(left<=right&&values[left]==leftValue){
                    left++;
                    leftCount++;
                }
                while(right>=left&&values[right]==rightValue){
                    right--;
                    rightCount++;
                }
                // Equal values belong to distinct participants.
                answer+=leftCount*rightCount;
            }
        }
    }
    cout<<answer<<'\n';
}

Source: Arena Olimpiici ↗