I have some problems with code for my classes. Even though it works correctly, I run out of time for half of the examples. Here's the task (I really did my best trying to translate it):
You have a permutation of numbers 1,2,...,n for some n. All consecutive numbers of permutations together create sequence a₁, a₂, a₊. Your task is to count how many arithmetic substrings of length 3 are present.
Input: In first line there is a number n (1 <= n <= 200 000). In the second line there is n numbers a₁, a₂, a₊ representing our permutation.
Output: The program needs to print out amount of arithmetic substrings of length 3 for permutations from entry. You can assume that the result won't be bigger than 1 000 000.
NOTE: arithmetic substrings most likely stand for arithmetic progression or something like that
#include <iostream>
using namespace std;
int main()
{
int input_length;
cin >> input_length;
int correct_sequences = 0;
bool* whether_itroduced = new bool[input_length + 1]{0}; // true - if number was already introduced and false otherwise.
for (int i = 0; i < input_length; i++)
{
int a;
cin >> a;
whether_itroduced[a] = true;
int range = min(input_length - a, a - 1); // max or min number that may be in the subsequence e.g. if introduced number a = 3, and all numbers are six, max range is 2 (3 - 2 = 1 and 3 + 2 = 5, so the longest possible subsequence is 1, 3, 5)
for (int r = range * -1; r <= range; r++) // r - there is a formula used to count arithmetic sequences -> an-1 = a1-r, an = a1, an+1 = a1+r, I have no idea how to explain it
{
if (r == 0) continue; // r cannot be 0
if (whether_itroduced[a - r] && !whether_itroduced[a + r])
correct_sequences++;
}
}
cout << correct_sequences;
}
example input: 5 1 5 4 2 3
correct output: 2
// {1,2,3} and {5,4,3}
example input: 5 1 2 3 4 5
correct output: 4
// {1,2,3} {2,3,4} {3,4,5} {1,3,5}
example input: 10 1 5 9 7 4 3 6 10 2 8
correct output: 4
// {4,3,2} {1,5,9} {5,4,3} {4,6,8}
I need to somehow come up with another algorithm that is less than quadratic in time. I can't really see all of the inputs and correct outputs, but I know that the biggest 'n' number is about 32000, so it's most likely that I run out of time because of the algorithm. Do you have any ideas about how can I improve it and make it work faster? Thanks for help!
EDIT: I found a guide explaining how to make the algorithm work quicker. Unluckily, I still have no idea how to write the code as the guide seems very unclear for me. Here's the guide:
Let’s say that x_1 is the smallest positive number, such that l_(ai-x1)≠l_(ai+x1) and l_(ai-y)=l_(ai+y) for 1 <= y < x_1. Then, the word created by l_(ai-x1+1), l_(ai-x1+2), ... , l_(ai+x1-1) is a palindrome, so a word l_(ai-x1+1), ... , l_ai is the same as word l_(ai+x1-1), ... , l_ai. Let’s say that x_2 is the smallest positive number, such that l_(ai-x2)≠l_(ai+x2) and l_(ai-y)=l_(ai+y) for x_1<y<x_2. Then, the word created by l_(ai-x2+1), l_(ai-x2+2), ... , l_(ai-x1-1), l_(ai+x1+1), ... , l_(ai+x2-1) is a palindrome. Also, you can define x_3, x_4, ... , x_k for some non-negative k (we assume, that x_(k+1) doesn’t exist). Considering the above definitions of sequence x_1, ... , x_k, we can assume, that the only arithmetic substrings of length 3 and a_i as a middle element, are a_i-x_j,a_i,a_i+x_j for 1 <= j <= k. If we could quickly compare two coherent subwords of words or subwords after reversal (it doesn’t make any sense in my language too), words l_1, l_2, ..., l_n, then using binary search, we would have been able to search for numbers x_1, ..., x_k. The structure allowing us to both compare coherent subwords of words and to update letters of word, is interval tree, in which we will store hashes (you can identify letters from words with positive numbers). In the apex, corresponding to some consistent subword l_a, l_(a+1), ..., l_b, there will be a hash of this subword h_([a,b])=l_a*p^0+l_(a+1)*p^1 + ... + l_(a+x)p^x+ ... + l_bp^(b-a). Changing the letter in a word and updating the tree is simple. We begin by changing the value in the leaf and for vertex values, which are not leaves and do have sons (?) responsible for compartment [a, a+x-1] and [a + x, a + 2x – 1] the new hash will be equal to h_([a,a+x-1])+h_([a+x,a+2x-1])*p^x. The update works in O(log n) time, assuming that we will remember all previous powers of p. To count the hash of a subword starting at a-th position and ending at b-th position, first break the interval [a,b] into base intervals. Let our base intervals be [a,c₁], [c₁+1,c₂], . . . . , [cₖ+1,b]. The hash of our word is: h[a,c₁]+h[c₁+1,c₂]*p^(c₁-a)+. . . +h[cᵢ+1,cᵢ+1]*p^(cᵢ-a)+. . . +h[cₖ+1,b]*p^(cₖ-a). Thus, one can count the hash of any consistent subword in O(log n) complexity. // base intervals - when we want to answer a query about the maximum on the interval [a,b], we need to find some set of partial intervals represented by the nodes of the interval tree. Such smaller intervals are called base intervals. Once we have the base intervals, we can reach into the tree and take the maximum from the values stored in the nodes corresponding to the base intervals, thus obtaining the result of the entire query// To use the presented structure in our task, we need two copies of it. We will keep the normal word in one binary tree and the reversed word in the other binary tree. This will allow us to arbitrarily compare both normal and inverted subwords. The entire algorithm has a computational (time) complexity of O(n log² n + m log² n) (or O(n log n + m log² n) if we apply a small optimization - we check if a word is not a palindrome before we start looking for all words xᵢ) and computational memory (space) complexity O(n).
Note: of course, indexes I have written in Word didn't survive, so here's screen from Word: https://i.sstatic.net/laT2N.jpg Guess that it's not worth your time to fix all those indexes.
1 2 3 4 5 6 ... n
, the number of 3-element arithmetic subsequences scales with n² (I believe it's actually floor((n² - 2n)/4)). So you will not be able to do better than quadratic time if you enumerate every such sequence. You need to find a way to count the sequences without enumerating them. \$\endgroup\$