#include <iostream>
#include <unordered_map>
#include <algorithm>
using namespace std;
long long result[125'000];
void extendWithSubarraySums(const int nums[], int n) {
int k = 0;
// Dodajemy sumy wszystkich możliwych ciągów spójnych
for (size_t start = 0; n > start; start++) {
long long sum = 0;
for (size_t end = start; end < n; end++) {
sum += nums[end];
result[k++] = sum;
}
}
}
long long ilosc = 0;
// Algorytm 3SUM
void zliczciagi(int n) {
if(n == 1)
return;
sort(result, result + n);
int Lm = 1;
int mainIndex = 0;
while(mainIndex < n - 1 && result[mainIndex] == result[mainIndex+1]){ //bierze ostatni index podciagu jednolitego
mainIndex++;
Lm++;
}
if(mainIndex == n - 1) { //cala tablica w jednej cyfrze
if(result[mainIndex] == 0) ilosc = n*(n-1)*(n-2)/6; //wzor na wybranie 3 indeksow z n
return;
}
int Ll;
int left;
int Lr;
int right;
while (mainIndex < n - 2 && result[mainIndex]<=0) { //zawsze musi byc miejsce na pare, oraz min 1 liczba ujemna
left = mainIndex + 1;
Ll = 1;
while(left < right-1 && result[left] == result[left+1]){ //right -1 aby nie nachodzily na siebie indexy
left++;
Ll++;
}
right = n - 1;
Lr = 1;
while (left +1 < right && result[right] == result[right - 1]) { //left +1 aby nie nachodzily na siebie indexy
right--;
Lr++;
}
while (left < right) {
int sum = result[mainIndex] + result[left] + result[right];
if (sum < 0){
left++;
Ll = 1;
while(left < right-1 && result[left] == result[left+1]){
left++;
Ll++;
}
}
else if (sum > 0){
right--;
Lr = 1;
while (left +1 < right && result[right] == result[right - 1]) {
right--;
Lr++;
}
}
else { //znaleziono
while (left < right-1 && result[left] == result[left + 1]) {
left++;
Ll++;
}
while (left +1 < right && result[right] == result[right - 1]) {
right--;
Lr++;
}
ilosc += Ll * Lr * Lm; //dodajemy do ilosci wszystkie mozliwe trojpary indexow
left++; // Aby uniknąć nieskończonej pętli, przesuwamy left i right
Ll = 1;
right--;
Lr = 1;
}
}
//kolejny indeks
mainIndex++;
Lm = 1;
while(mainIndex < n - 1 && result[mainIndex] == result[mainIndex+1]){
mainIndex++;
Lm++;
}
}
}
int T[500];
int main() {
int n;
cin>>n;
for(int i=0;i<n;i++)
cin>>T[i];
long long resMax = (n*(n+1))/2;
extendWithSubarraySums(T,n); //maksymalny spojny podciag
sort(result, result + resMax);
zliczciagi(resMax);
cout<<ilosc;
return 0;
}
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 | #include <iostream> #include <unordered_map> #include <algorithm> using namespace std; long long result[125'000]; void extendWithSubarraySums(const int nums[], int n) { int k = 0; // Dodajemy sumy wszystkich możliwych ciągów spójnych for (size_t start = 0; n > start; start++) { long long sum = 0; for (size_t end = start; end < n; end++) { sum += nums[end]; result[k++] = sum; } } } long long ilosc = 0; // Algorytm 3SUM void zliczciagi(int n) { if(n == 1) return; sort(result, result + n); int Lm = 1; int mainIndex = 0; while(mainIndex < n - 1 && result[mainIndex] == result[mainIndex+1]){ //bierze ostatni index podciagu jednolitego mainIndex++; Lm++; } if(mainIndex == n - 1) { //cala tablica w jednej cyfrze if(result[mainIndex] == 0) ilosc = n*(n-1)*(n-2)/6; //wzor na wybranie 3 indeksow z n return; } int Ll; int left; int Lr; int right; while (mainIndex < n - 2 && result[mainIndex]<=0) { //zawsze musi byc miejsce na pare, oraz min 1 liczba ujemna left = mainIndex + 1; Ll = 1; while(left < right-1 && result[left] == result[left+1]){ //right -1 aby nie nachodzily na siebie indexy left++; Ll++; } right = n - 1; Lr = 1; while (left +1 < right && result[right] == result[right - 1]) { //left +1 aby nie nachodzily na siebie indexy right--; Lr++; } while (left < right) { int sum = result[mainIndex] + result[left] + result[right]; if (sum < 0){ left++; Ll = 1; while(left < right-1 && result[left] == result[left+1]){ left++; Ll++; } } else if (sum > 0){ right--; Lr = 1; while (left +1 < right && result[right] == result[right - 1]) { right--; Lr++; } } else { //znaleziono while (left < right-1 && result[left] == result[left + 1]) { left++; Ll++; } while (left +1 < right && result[right] == result[right - 1]) { right--; Lr++; } ilosc += Ll * Lr * Lm; //dodajemy do ilosci wszystkie mozliwe trojpary indexow left++; // Aby uniknąć nieskończonej pętli, przesuwamy left i right Ll = 1; right--; Lr = 1; } } //kolejny indeks mainIndex++; Lm = 1; while(mainIndex < n - 1 && result[mainIndex] == result[mainIndex+1]){ mainIndex++; Lm++; } } } int T[500]; int main() { int n; cin>>n; for(int i=0;i<n;i++) cin>>T[i]; long long resMax = (n*(n+1))/2; extendWithSubarraySums(T,n); //maksymalny spojny podciag sort(result, result + resMax); zliczciagi(resMax); cout<<ilosc; return 0; } |
English