One day, Twilight Sparkle is interested in how to sort a sequence of
integers a1, a2, ..., an in non-decreasing order. Being a young
unicorn, the only operation she can perform is a unit shift. That is,
she can move the last element of the sequence to its beginning:
a1, a2, ..., an → an, a1, a2, ..., an - 1. Help Twilight Sparkle to
calculate: what is the minimum number of operations that she needs to
sort the sequence?
Input
The first line contains an integer n (2 ≤ n ≤ 105). The second
line contains n integer numbers a1, a2, ..., an (1 ≤ ai ≤ 105).
Output
If it's impossible to sort the sequence output -1. Otherwise
output the minimum number of operations Twilight Sparkle needs to sort
it.
Examples
input
2
2 1
output
1
input
3
1 3 2
output
-1
input
2
1 2
output
0
Above is the problem and now I am confused because the solution down there used a variable called "s" and played around it for some reason but I don't know why was that variable used, if someone can tell me I'll be thankful.
#include <iostream>
#include <vector>
using namespace std;
int main()
{
int n, s, v(0);
cin >> n;
vector<int> a(n);
for (int i = 0; i < n; i++) cin >> a[i];
for (int i = 0; i < n - 1; i++) if (a[i] > a[i + 1]) s = i, v++;
if (a[n - 1] > a[0]) s = n - 1, v++;
if (v == 0) cout << 0 << endl;
else if (v > 1) cout << -1 << endl;
else cout << n - 1 - s << endl;
return 0;
}
Now here is my own solution, it works and everything except on a 10^5(and around that) size array but the question time limit is only 1000 ms, and mine exceeds that limit due to the nested loops making it go over O(10^8) which is 1000 ms on their systems.
#include <bits/stdc++.h>
#define fl(i,n) for(int i = 0; i < n; i++)
#define ll long long
#define nl endl
#define pb push_back
#define mp make_pair
#define PII pair<int,int>
#define EPS 1e-9
#define INF 1e9
using namespace std;
bool check(int a[], int n){
for(int i = 0; i < n-1; i++){
if(a[i] <= a[i+1]) continue;
return false;
}
return true;
}
int main()
{
int n;
cin >> n;
int a[n]; //is out of standard i know but it's accepted in the contest's compiler so we just use it
for(int i = 0; i < n; i++){
cin >> a[i];
}
if(check(a,n)){
cout << 0;
return 0;
}
int ret = 0;
for(int i = 0; i < n-1; i++){
ret++;
for(int j = n-1; j > 0; j--)
a[j] ^= a[j-1] ^= a[j] ^= a[j-1]; //is xor swap
if(check(a,n)){
cout << ret;
return 0;
}
}
cout << -1;
return 0;
}
PS: I TRACED the solution's code and even if I get the correct answers I simply don't know what it refers to.
The other person's implementation relies on an algorithmic insight. The only way a sequence can be sorted by moving back to front is if the sequence is made of two already-sorted sections. Then, the goal is to check how many unsorted discontinuities exist, and where they are. That's what s appears to be used for: the index of the (last) discontinuity of the sequence. v is the count of discontinuities.
If there are 0, it's already sorted. If more than 1, it's unsortable. If it's exactly one, then you can easily figure out how many shifts you need to perform to pull the discontinuity back to the front, using it's location (s) in the original sequence.
The only extra line of code is the special case of checking for the discontinuity around end of the sequence.
My recommendation: Generate a larger set of test sequences, and print v and s for each one.
Related
Hey there! In the following code, I am trying to count frequency of each non zero number
My intention of the code is to update freq after testing each case using nested loop but value of freq is not updating. freq value remains to be either 0 or 1. I tried to debug but still ending up with the same bug.
Code:
#include <bits/stdc++.h>
using namespace std;
int main() {
int size;
cin>>size;
int freq=0;
int d[size];
for(int i=0;i<size;i++){ //To create array and store values in it
cin>>d[i];
}
for(int i=0;i<size;i++){
if(d[i]==0 )continue;
for(int j=0;j<size;j++){
if(d[i]==d[j]){
freq=freq+1;
d[j]=0;
}
}
cout<<"Frequency of number "<<d[i]<<" is "<<freq<<endl;
d[i]=0;
freq=0;
}
}
Input:
5
1 1 2 2 5
Expected output:
Frequency of number 1 is 2
Frequency of number 2 is 2
Frequency of number 5 is 1
Actual output:
Frequency of number 0 is 1
Frequency of number 0 is 1
Frequency of number 0 is 1
Frequency of number 0 is 1
Frequency of number 0 is 1
Some one please debug the code and fix it. Open for suggestions.
#include <bits/stdc++.h>
This is not standard C++. Don't use this. Include individual standard headers as you need them.
using namespace std;
This is a bad habit. Don't use this. Either use individual using declarations for identifiers you need, such as using std::cout;, or just prefix everything standard in your code with std:: (this is what most people prefer).
int d[size];
This is not standard C++. Don't use this. Use std::vector instead.
for(int j=0;j<size;j++){
if(d[i]==d[j]){
Assume i == 0. The condition if(d[i]==d[j]) is true when i == j, that is, when j == 0. So the next thing that happens is you zero out d[0].
Now assume i == 1. The condition if(d[i]==d[j]) is true when i == j, that is, when j == 1. So the next thing that happens is you zero out d[1].
Now assume i == 2. The condition if(d[i]==d[j]) is true when i == j, that is, when j == 2. So the next thing that happens is you zero out d[2].
Now assume i == 3 ...
So you zero out every element of the array the first time you see it, and if(d[i]==d[j]) never becomes true when i != j.
This can be fixed by changing the inner loop to
for (int j = i + 1; j < size; j++) {
This will output freq which is off by one, because this loop doesn't count the first element. Change freq = 0 to freq = 1 to fix that. I recommend having one place where you have freq = 1. A good place to place this assignment is just before the inner loop.
Note, I'm using spaces around operators and you should too. Cramped code is hard to read.
Here is a live demo of your program with all the aforementioned problems fixed. No other changes are made.
To build an histogram, you actually need to collect history.
Example:
int main() {
int size;
cin >> size;
int d[size];
int hist[size + 1]{}; // all zeroes - this is for the histogram
for (int i = 0; i < size; i++) { // To create array and store values in it
cin >> d[i];
}
for (int i = 0; i < size; i++) {
++hist[d[i]];
}
for(int i = 0; i < size; ++i) {
cout << "Frequency of number " << i << " is " << hist[i] << endl;
}
}
Note: VLAs (Variable Length Arrays) are not a standard C++ feature. Use std::vector instead.
A slightly different approach would be to not be limited by the size parameter when taking the input values. std::map the value to a count instead:
#include <iostream>
#include <vector>
#include <map>
int main() {
int size;
if(not (std::cin >> size) or size < 1) return 1;
std::map<int, unsigned long long> hist; // number to count map
for(int value; size-- > 0 && std::cin >> value;) {
++hist[value];
}
for(auto[value, count] : hist) {
std::cout << "Frequency of number " << value << " is " << count << '\n';
}
}
This is a question from Codechef but please bear with me.
https://www.codechef.com/ZCOPRAC/problems/ZCO12004
The contest is for the preparation of the Zonal Computing Olympiad held in India, so its not a competitive contest from which I'd earn something as such. Just need a little help to see what is wrong with my code, because I have a feeling I've overlooked something big and stupid. :P
The problem basically states:
Imagine there is a vector or array such that the last element is
linked to the first one. Find the lowest possible sum from adding at
least one of each adjacent pairs of elements. (refer to link please)
So answer for {1,2,1,2,2} output would be 4 by adding 1+1+2.
Here is my solution:
Basically what it does is that it iterates backwards, from the end of the vector to the beginning, and stores the lowest possible sum that can be achieved from that vector onwards, in vector M. Done using dynamic programming, basically.
The first two elements of M are the possible answers. Then I do some checks to see which is possible. If M[1] is less than M[0] then the last element of the array/vector should have been included in the sum calculated in M[1].
#include <algorithm>
#include <iostream>
#include <vector>
#define print(arr) for(auto pos = arr.begin(); pos != arr.end(); ++pos) cout << *pos << " "; cout << endl;
typedef long long int ll;
using namespace std;
int main() {
int N;
ll x;
cin >> N;
vector <ll> A;
vector <ll> M(N+2);
fill(M.begin(),M.end(),0);
for (int i = 0; i < N; i++) {
cin >> x;
A.push_back(x);
}
for (int i = N-1; i >= 0; i--) {
M[i] = A[i]+*min_element(M.begin()+i+1, M.begin()+i+3);
}
if (M[0] <= M[1]) cout << M[0] << endl;
else if (M[1] < M[0]) {
if (M[N-1] <= (M[N-2])) cout << M[1] << endl;
else cout << M[0] << endl;
}
}
However, I could not pass 2 of the test cases in subtask 2. I think the last part of my code is incorrect. Any idea what I could be doing wrong? Either that, or I have misunderstood the question. The term "adjacent pairs" is sort of ambiguous. So if there are 4 numbers 3,4,5,6 does adjacent pairs mean adjacent pairs to be {(3,4) (4,5) (5,6) (6,3)} or {either (3,4) and (5,6) or (4,5) and (6,3)}? My code considers the former.
EDIT:
Thanks a lot #User_Targaryen cleared some doubts about this question! Basically my implementation was the same as yours as my idea behind using dynamic programming was the same. Only that in this case my M (your dp) was the reverse of yours. Anyway I got AC! :) (I had left some silly debugging statements and was wondering for 15 mins what went wrong xD) Updated solution:
#include <algorithm>
#include <iostream>
#include <vector>
#define print(arr) for(auto pos = arr.begin(); pos != arr.end(); ++pos) cout << *pos << " "; cout << endl;
typedef long long int ll;
using namespace std;
int main() {
int N;
ll x, sum = 0;
cin >> N;
vector <ll> A;
vector <ll> M(N+2);
fill(M.begin(),M.end(),0);
for (int i = 0; i < N; i++) {
cin >> x;
A.push_back(x);
}
for (int i = N-1; i >= 0; i--) {
M[i] = A[i]+*min_element(M.begin()+i+1, M.begin()+i+3);
}
//print(M);
reverse(A.begin(), A.end());
vector <ll> M2(N+2);
fill(M2.begin(),M2.end(),0);
for (int i = N-1; i >= 0; i--) {
M2[i] = A[i]+*min_element(M2.begin()+i+1, M2.begin()+i+3);
}
//print(M2);
cout << min(M[0], M2[0]) << endl;
}
I am attaching my accepted solution here:
#include<iostream>
using namespace std;
int main()
{
int i,j,k,n;
cin>>n;
int a[n],dp1[n],dp2[n];
int ans;
for(i=0;i<n;i++)
{
cin>>a[i];
dp1[i]=0;
dp2[i]=0;
}
if(n <= 2)
cout<< min(a[0],a[1]);
else{
i = 2;
dp1[0] = a[0];
dp1[1] = a[1];
while (i < n){
dp1[i] = a[i] + min(dp1[i-1],dp1[i-2]);
i = i + 1;
}
dp2[0] = a[n-1];
dp2[1] = a[n-2];
i = n-3;
j = 2;
while(i >= 0){
dp2[j] = a[i] + min(dp2[j-1],dp2[j-2]);
i = i - 1;
j = j + 1;
}
ans = min(dp1[n-1], dp2[n-1]);
cout<<ans;
}
return 0;
}
dp1[i] means the most optimal solution till now by including the i-th element in the solution
dp2[i] means the most optimal solution till now by including the i-th element in the solution
dp1[] is calculated from left to right, while dp2[] is calculated from right to left
The minimum of dp1[n-1] and dp2[n-1] is the final answer.
I did your homework!
Edit: #Alex: Dynamic Programming is something that is very difficult to teach. It is something that comes naturally with some practice. Let us consider my solution (forget about your solution for some time):
dp1[n-1] means that I included the last element definitely in the solution, and the constraint that at least one of any 2 adjacent elements need to picked, is satisfied because it always follows:
dp1[i] = a[i] + min(dp1[i-1],dp1[i-2]);
dp2[n-1] means that I included the first element definitely in the solution, and the constraint that at least one of any 2 adjacent elements need to picked, is satisfied also.
So, the minimum of the above two, will give me the final result.
The idea in your M[i] array is "the minimum cost for a solution, assuming the index i is included in it".
The condition if (M[0] <= M[1]) means "if including index 0 is better than not including it, done".
If this condition doesn't hold, then, first of all, the check if (M[1] < M[0]) is superfluous - remove it. It won't fix any bugs, but will at least reduce confusion.
If the condition is false, you should output M[1], but only if it corresponds to a valid solution. That is, since index 0 is not chosen, the last index should be chosen. However, with your data structure it's impossible to know whether M[1] corresponds to a solution that chose last index - this information is lost.
To fix this, consider building two arrays - add e.g. an array L whose meaning is "the minimum cost for a solution, assuming the index i is included in it, and also index N-1 is included in it".
Then, at the end of your program, output the minimum of M[0] and L[1].
So I had to write n-amount of real numbers into vector and then print the biggest from it.
#include <iostream>
#include <vector>
using namespace std;
void printMax(vector<double>);
int main()
{
vector<double> vct;
double n;
while(cin >> n)
vct.push_back(n);
printMax(vct);
return 0;
}
void printMax(vector<double> x)
{
int max;
for(int i = 1; i < x.size(); i++)
{
if(x[i] > x[i - 1]) max = x[i];
else continue;
}
cout << "Max = \t" << max << endl;
}
When I start this program it lets me to enter numbers but as soon as I press ctrl+z and enter it crashes and says : vector subscript out of the range line: 1201. I think that an issue is with void printMax part .
You have to start the following loop with i = 1:
for (int i = 1; i < x.size(); i++){
if (x[i] > x[i - 1])
max = x[i];
// else continue superfluous
}
because if i is 0, i - 1 will be negative one (or the biggest value of unsigned int there is). That's not possibly a valid index in this case.
Also, why are you using int for said real numbers?
In fact, there's a simpler way to find the maximum element of a vector. It does not involve a comparison of the two consecutive elements, but rather comparison of the current max against each element. Improve your algorithm, or perhaps, use std::max_element.
And when I wrote improve, I actually meant correct it.
in the first round of your for loop x=0 and you use x[i - 1] ie. x[-1].
In the for loop, when i = 0 you are accessing x[i - 1] (i.e. x[-1]).
You may want to change to
int max = x[0];
for (int i = 1; i < x.size(); i++){
if(x[i] > max) max = x[i]; // Compare with actual max
If your first index is 0, then the line x[i] > x[i - 1] becomes x[0] > x[-1], and x[-1] is always out if bounds. Change your loop to start at int i = 1 and it should resolve your problem.
So, I've been working through a problem in Bjarne Stroustrup's Programming: Principles and Practices Using C++ for my own benefit, and this problem has stumped me for a couple of days now.
I'm supposed to implement the classic Sieve of Eratosthenes algorithm with the tools learned by chapter 4 (that's not a lot) and this is what I have so far:
#include <iostream>
#include <vector>
#include <cmath>
using namespace std;
int main()
{
int p = 2;
int n = 0;
vector<int> nums{ 1, 1 };
cout << "Enter an integer greater than 1:\n";
cin >> n;
for (int i = 2; i <= n; ++i)
nums.push_back(0);
while (p < sqrt(n))
{
for (int i = 2; (i*p) <= n; ++i)
{
nums[i*p] = 1;
}
for (int i = (p+1); i <= n; ++i)
{
if (nums[i] == 0)
{
p = i;
break;
}
}
}
for (int i = 0; i <= n; ++i)
{
if (nums[i] == 0)
cout << i << '\n';
}
return 0;
}
This code is SOOO close to working but no cigar. It only prints the prime numbers after and including 5, it does not print 2 or 3. I know that the problem is due to the fact that my marking loop is marking nums[2] and nums[3], so I tried to add the following line of code to insure that 2 and 3 were unmarked, because they were used as the p starting values:
nums[p] = 0;
I put that line in-between the two for-loops nested within the while-loop. I have no idea how, but that somehow causes an infinite loop that I've tried for hours to fix. I'm really at my wit's end here.
NOTE: I've been testing this with n = 23.
So, after fixing your first loop starting point, the issue is the next loop.
Because the next loop always starts at 0 and looks for the next prime number, it is going to always find 2, and that will cause an infinite loop.
To solve this issue, start your search for the next prime, from the previous value:
for(int i = p + 1; i <= n; ++i)
I solved this problem but I got TLE Time Limit Exceed on online judge
the output of program is right but i think the way can be improved to be more efficient!
the problem :
Given n integer numbers, count the number of ways in which we can choose two elements such
that their absolute difference is less than 32.
In a more formal way, count the number of pairs (i, j) (1 ≤ i < j ≤ n) such that
|V[i] - V[j]| < 32. |X|
is the absolute value of X.
Input
The first line of input contains one integer T, the number of test cases (1 ≤ T ≤ 128).
Each test case begins with an integer n (1 ≤ n ≤ 10,000).
The next line contains n integers (1 ≤ V[i] ≤ 10,000).
Output
For each test case, print the number of pairs on a single line.
my code in c++ :
int main() {
int T,n,i,j,k,count;
int a[10000];
cin>>T;
for(k=0;k<T;k++)
{ count=0;
cin>>n;
for(i=0;i<n;i++)
{
cin>>a[i];
}
for(i=0;i<n;i++)
{
for(j=i;j<n;j++)
{
if(i!=j)
{
if(abs(a[i]-a[j])<32)
count++;
}
}
}
cout<<count<<endl;
}
return 0;
}
I need help how can I solve it in more efficient algorithm ?
Despite my previous (silly) answer, there is no need to sort the data at all. Instead you should count the frequencies of the numbers.
Then all you need to do is keep track of the number of viable numbers to pair with, while iterating over the possible values. Sorry no c++ but java should be readable as well:
int solve (int[] numbers) {
int[] frequencies = new int[10001];
for (int i : numbers) frequencies[i]++;
int solution = 0;
int inRange = 0;
for (int i = 0; i < frequencies.length; i++) {
if (i > 32) inRange -= frequencies[i - 32];
solution += frequencies[i] * inRange;
solution += frequencies[i] * (frequencies[i] - 1) / 2;
inRange += frequencies[i];
}
return solution;
}
#include <bits/stdc++.h>
using namespace std;
int a[10010];
int N;
int search (int x){
int low = 0;
int high = N;
while (low < high)
{
int mid = (low+high)/2;
if (a[mid] >= x) high = mid;
else low = mid+1;
}
return low;
}
int main() {
cin >> N;
for (int i=0 ; i<N ; i++) cin >> a[i];
sort(a,a+N);
long long ans = 0;
for (int i=0 ; i<N ; i++)
{
int t = search(a[i]+32);
ans += (t -i - 1);
}
cout << ans << endl;
return 0;
}
You can sort the numbers, and then use a sliding window. Starting with the smallest number, populate a std::deque with the numbers so long as they are no larger than the smallest number + 31. Then in an outer loop for each number, update the sliding window and add the new size of the sliding window to the counter. Update of the sliding window can be performed in an inner loop, by first pop_front every number that is smaller than the current number of the outer loop, then push_back every number that is not larger than the current number of the outer loop + 31.
One faster solution would be to first sort the array, then iterate through the sorted array and for each element only visit the elements to the right of it until the difference exceeds 31.
Sorting can probably be done via count sort (since you have 1 ≤ V[i] ≤ 10,000). So you get linear time for the sorting part. It might not be necessary though (maybe quicksort suffices in order to get all the points).
Also, you can do a trick for the inner loop (the "going to the right of the current element" part). Keep in mind that if S[i+k]-S[i]<32, then S[i+k]-S[i+1]<32, where S is the sorted version of V. With this trick the whole algorithm turns linear.
This can be done constant number of passes over the data, and actually can be done without being affected by the value of the "interval" (in your case, 32).
This is done by populating an array where a[i] = a[i-1] + number_of_times_i_appears_in_the_data - informally, a[i] holds the total number of elements that are smaller/equals to i.
Code (for a single test case):
static int UPPER_LIMIT = 10001;
static int K = 32;
int frequencies[UPPER_LIMIT] = {0}; // O(U)
int n;
std::cin >> n;
for (int i = 0; i < n; i++) { // O(n)
int x;
std::cin >> x;
frequencies[x] += 1;
}
for (int i = 1; i < UPPER_LIMIT; i++) { // O(U)
frequencies[i] += frequencies[i-1];
}
int count = 0;
for (int i = 1; i < UPPER_LIMIT; i++) { // O(U)
int low_idx = std::max(i-32, 0);
int number_of_elements_with_value_i = frequencies[i] - frequencies[i-1];
if (number_of_elements_with_value_i == 0) continue;
int number_of_elements_with_value_K_close_to_i =
(frequencies[i-1] - frequencies[low_idx]);
std::cout << "i: " << i << " number_of_elements_with_value_i: " << number_of_elements_with_value_i << " number_of_elements_with_value_K_close_to_i: " << number_of_elements_with_value_K_close_to_i << std::endl;
count += number_of_elements_with_value_i * number_of_elements_with_value_K_close_to_i;
// Finally, add "duplicates" of i, this is basically sum of arithmetic
// progression with d=1, a0=0, n=number_of_elements_with_value_i
count += number_of_elements_with_value_i * (number_of_elements_with_value_i-1) /2;
}
std::cout << count;
Working full example on IDEone.
You can sort and then use break to end loop when ever the range goes out.
int main()
{
int t;
cin>>t;
while(t--){
int n,c=0;
cin>>n;
int ar[n];
for(int i=0;i<n;i++)
cin>>ar[i];
sort(ar,ar+n);
for(int i=0;i<n;i++){
for(int j=i+1;j<n;j++){
if(ar[j]-ar[i] < 32)
c++;
else
break;
}
}
cout<<c<<endl;
}
}
Or, you can use a hash array for the range and mark occurrence of each element and then loop around and check for each element i.e. if x = 32 - y is present or not.
A good approach here is to split the numbers into separate buckets:
constexpr int limit = 10000;
constexpr int diff = 32;
constexpr int bucket_num = (limit/diff)+1;
std::array<std::vector<int>,bucket_num> buckets;
cin>>n;
int number;
for(i=0;i<n;i++)
{
cin >> number;
buckets[number/diff].push_back(number%diff);
}
Obviously the numbers that are in the same bucket are close enough to each other to fit the requirement, so we can just count all the pairs:
int result = std::accumulate(buckets.begin(), buckets.end(), 0,
[](int s, vector<int>& v){ return s + (v.size()*(v.size()-1))/2; });
The numbers that are in non-adjacent buckets cannot form any acceptable pairs, so we can just ignore them.
This leaves the last corner case - adjacent buckets - which can be solved in many ways:
for(int i=0;i<bucket_num-1;i++)
if(buckets[i].size() && buckets[i+1].size())
result += adjacent_buckets(buckets[i], buckets[i+1]);
Personally I like the "occurrence frequency" approach on the one bucket scale, but there may be better options:
int adjacent_buckets(const vector<int>& bucket1, const vector<int>& bucket2)
{
std::array<int,diff> pairs{};
for(int number : bucket1)
{
for(int i=0;i<number;i++)
pairs[i]++;
}
return std::accumulate(bucket2.begin(), bucket2.end(), 0,
[&pairs](int s, int n){ return s + pairs[n]; });
}
This function first builds an array of "numbers from lower bucket that are close enough to i", and then sums the values from that array corresponding to the upper bucket numbers.
In general this approach has O(N) complexity, in the best case it will require pretty much only one pass, and overall should be fast enough.
Working Ideone example
This solution can be considered O(N) to process N input numbers and constant in time to process the input:
#include <iostream>
using namespace std;
void solve()
{
int a[10001] = {0}, N, n, X32 = 0, ret = 0;
cin >> N;
for (int i=0; i<N; ++i)
{
cin >> n;
a[n]++;
}
for (int i=0; i<10001; ++i)
{
if (i >= 32)
X32 -= a[i-32];
if (a[i])
{
ret += a[i] * X32;
ret += a[i] * (a[i]-1)/2;
X32 += a[i];
}
}
cout << ret << endl;
}
int main()
{
int T;
cin >> T;
for (int i=0 ; i<T ; i++)
solve();
}
run this code on ideone
Solution explanation: a[i] represents how many times i was in the input series.
Then you go over entire array and X32 keeps track of number of elements that's withing range from i. The only tricky part really is to calculate properly when some i is repeated multiple times: a[i] * (a[i]-1)/2. That's it.
You should start by sorting the input.
Then if your inner loop detects the distance grows above 32, you can break from it.
Thanks for everyone efforts and time to solve this problem.
I appreciated all Attempts to solve it.
After testing the answers on online judge I found the right and most efficient solution algorithm is Stef's Answer and AbdullahAhmedAbdelmonem's answer also pavel solution is right but it's exactly same as Stef solution in different language C++.
Stef's code got time execution 358 ms in codeforces online judge and accepted.
also AbdullahAhmedAbdelmonem's code got time execution 421 ms in codeforces online judge and accepted.
if they put detailed explanation to there algorithm the bounty will be to one of them.
you can try your solution and submit it to codeforces online judge at this link after choosing problem E. Time Limit Exceeded?
also I found a great algorithm solution and more understandable using frequency array and it's complexity O(n).
in this algorithm you only need to take specific range for each inserted element to the array which is:
begin = element - 32
end = element + 32
and then count number of pair in this range for each inserted element in the frequency array :
int main() {
int T,n,i,j,k,b,e,count;
int v[10000];
int freq[10001];
cin>>T;
for(k=0;k<T;k++)
{
count=0;
cin>>n;
for(i=1;i<=10000;i++)
{
freq[i]=0;
}
for(i=0;i<n;i++)
{
cin>>v[i];
}
for(i=0;i<n;i++)
{
count=count+freq[v[i]];
b=v[i]-31;
e=v[i]+31;
if(b<=0)
b=1;
if(e>10000)
e=10000;
for(j=b;j<=e;j++)
{
freq[j]++;
}
}
cout<<count<<endl;
}
return 0;
}
finally i think the best approach to solve this kind of problems to use frequency array and count number of pairs in specific range because it's time complexity is O(n).