Я пытаюсь решить проблему, которая выглядит примерно так:
Мне дано n чисел (1 <= n <= 10 ^ 5). Мне нужно написать сумму всех чисел слева, которые меньше текущего числа, и повторить процесс для всех n чисел. Затем Я должен найти сумму всех ранее полученных сумм. (Каждое число N, 0 <= N <= 10 ^ 6). </p>
Например,
1 5 3 6 4
less1 less5 less3 less6 less4
(0) + (1) + (1)+(1+5+3)+(1+3)
0 + 1 + 1 + 9 + 4
= 15
Тривиальным решением этой проблемы будет запуск двух циклов, и для каждого из заданного числа найдите сумму всех чисел, меньших, чем это число, и, наконец, дайте сумму этих сумм в качестве выходных данных. Сложность по времени равна O (n ^ 2).
Я думаю, что лучшее решение O (nlogn) для этой проблемы с использованием Binary Indexed Tree (Fenwick Tree).
Для каждого числа я добавлю каждое из чисел в глобальном массиве a и выполню две очевидные операции BIT. Я думаю, что временная сложность этого алгоритма равна O (nlogn), которая, если true, очевидно, лучше, чем предыдущая O (n ^ 2).
Я реализовал код на C ++.
#include<iostream>
#include<cstdio>
using namespace std;
#define max 1000001
long int a[max];
void add(long int v,int idx){
while(idx<max){
a[idx] += v;
idx += (idx & -idx);
}
}
long int sum(int idx){
long int s=0;
while(idx>0){
s += a[idx];
idx -= (idx & -idx);
}
return s;
}
int main()
{
int t;
scanf("%d",&t);
for(int w=0;w<t;w++){
int n;
scanf("%d",&n);
for(int i=0;i<max;i++)
a[i]=0;
int arr[n];
for(int i=0;i<n;i++)
scanf("%d",&arr[i]);
long long res=0;
for(int i=0;i<n;i++){
if(arr[i]!=0){
add(arr[i],arr[i]);
res += (sum(arr[i]-1));
}
}
printf("%lld\n",res);
}
return 0;
}
У меня два вопроса:
Во-первых, я делаю это правильно? / Правильна ли моя логика?
Во-вторых, если я прав насчет временной сложности, чтобы быть O (nlogn), то почему он работает медленно? Можете ли вы помочь мне с дальнейшей оптимизацией?
Получено за 1,41 секунды. В то же время я обновил окончательно принятый код. Есть предложения по оптимизации?
Основываясь на комментариях, я попробовал свою собственную функцию для более быстрого ввода-вывода, но, тем не менее, она не идет своим чередом. Это моя функция для быстрого ввода-вывода:
inline int read(){
char c=getchar_unlocked();
int n=0;
while(!(c>='0' && c<='9'))
c=getchar_unlocked();
while(c>='0' && c<='9'){
n=n*10 + (c-'0');
c=getchar_unlocked();
}
return n;
}
Это ссылка на проблему:
http://www.spoj.pl/problems/DCEPC206/
Если есть кто-то, кто может решить это, пожалуйста, дайте мне знать.
Спасибо.