Próbuję rozwiązać problem, który jest mniej więcej tak:Propozycje optymalizacji kodu, aby przekazać TLE na SPOJ
Ja podanych liczb n (n = 1 < < = 10^5) .I Muszę napisać sumę wszystkich liczb po lewej, które są mniejsze od aktualnej liczby i powtórzyć proces dla wszystkich liczb n. Następnie muszę znaleźć sumę wszystkich poprzednio uzyskanych sum. (Każda liczba N, 0 < = N < = 10^6).
Na przykład
1 5 3 6 4
less1 less5 less3 less6 less4
(0) + (1) + (1)+(1+5+3)+(1+3)
0 + 1 + 1 + 9 + 4
= 15
Trywialny rozwiązanie tego problemu będzie uruchomić dwie pętle i dla każdego z podanym numerem znaleźć sumę wszystkich liczb mniejszych od tej liczby i wreszcie dać sumę tych suma jako wynik. Złożoność czasu wynosi O (n^2).
Myślę, że lepsze rozwiązanie O (nlogn) dla tego problemu przy użyciu binarnie indeksowanego drzewa (drzewa Fenwick). Dla każdego numeru dodam każdą z liczb w tablicy globalnej a i wykonam dwie oczywiste operacje BIT.Myślę, że złożoność czasowa tego algorytmu to O (nlogn), która jeśli jest prawdziwa jest oczywiście lepsza niż poprzednia O (n^2).
Zaimplementowałem kod w 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;
}
Mam dwa pytania:
pierwsze, robię to prawidłowe?/Czy moja logika jest poprawna?
Po drugie, jeśli mam rację co do złożoności czasu, która ma być O (nlogn), to dlaczego działa wolno? Czy możesz mi pomóc z dalszymi optymalizacjami?
Został zaakceptowany przez 1,41 sekundy. W tym samym czasie zaktualizowałem mój ostatecznie zaakceptowany kod. Sugestię optymalizacji?
Na podstawie uwag Próbowałem własną funkcję do szybszego I/O, ale nadal to nie będzie moje way.This jest moja funkcja do szybkiego I/O:
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;
}
tym odnośnikiem do problemu :
http://www.spoj.pl/problems/DCEPC206/
Jeśli jest ktoś, kto jest niepełnosprawny go rozwiązać, proszę dać mi znać. Dzięki.
Czy możesz podać przykład? Na przykład, jaki jest oczekiwany wynik dla '5 2 3 9 6 4'? – IVlad
@ivlad: Zmieniłem to pytanie i dałem przykład dla niego. BTW dla twojego wejścia mój kod daje 27. –
To wciąż jest niejasne. Czy możesz podać przykład "krok po kroku"? – zvrba