Advertisement
Not a member of Pastebin yet?
Sign Up,
it unlocks many cool features!
- /*
- Zadatak: SUME
- Složenost: N(log N) za sort, N(log N) za brojanje
- Autor zadatka: Alen Rakipović
- Autor rješenja: Kristijan Burnik, udruga informatičara Božo Težak
- Gmail: kristijanburnik
- */
- #include <iostream>
- #include <cstdlib>
- #include <algorithm>
- using namespace std;
- int a[5000];
- int exists(int start,int end,int key) {
- // binarna pretraga kljuca u nekom ukljucivom intervalu [start,end]
- while (start <= end) {
- int mid = (start + end) /2;
- if (key > a[mid])
- start = mid + 1;
- else if (key < a[mid])
- end = mid - 1;
- else
- return 1;
- }
- return 0;
- }
- int main() {
- int n;
- cin >> n;
- // broj nula koje se pojavljuju u nizu
- int zerocount = 0;
- // unos
- for (int i = 0 ; i < n; i++) {
- cin >> a[i];
- // vodimo racunu o broju nula koje su u nizu zbog jedne iznimke - triplet: (0,0,0)
- if (a[i] == 0) zerocount++;
- }
- // sortiramo niz jer cemo nad istim raditi binarnu pretragu
- sort(a,a+n);
- // iznimka postoji kod pojave barem tri nule, tada je to jedan triplet i odmah ga brojimo
- int unique = (zerocount >= 3);
- // postavljamo pocetne granice - koje su ukljucive!
- int start = 0;
- int end = n-1;
- // trazimo tri broja koji daju 0 u sumi
- int left,right,middle;
- // ima smisla brojati dok se krajevi ne poklope
- // te dok je lijevi kraj negativan ili 0
- while (start < end && a[start] <= 0) {
- // postavljamo fiksni desni kraj
- end = n-1;
- // lijevi broj je uzet s lijevog dijela niza (brojevi koji su <= 0)
- left = a[start];
- // ima smisla brojati dok se krajevi ne poklope
- // te dok je desni kraj pozitivan
- while (start < end && a[end] > 0) {
- // desni broj je pozitivan
- right = a[end];
- // zbrojimo lijevi i desni broj, njegova negacija je srednji broj
- middle = -(left+right);
- // pronadji srednji u granicama [start+1, end-1 ] i broji kao novi triplet ako postoji
- unique += exists( start+1 , end-1 , middle );
- // pomici desnu granicu
- // (malo optimizacije jer se brojevi mogu ponavljati, a trazimo samo jedinstvene triplete!)
- while (start < end && a[end]==right) end--;
- }
- // pomici lijevu granicu (takodjer malo optimizacije)
- while (start < end && a[start]==left) start++;
- }
- // ispisi koliko je izbrojano tripleta
- cout << unique << endl;
- return 0;
- }
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement