2015-06-05 3 views
3

я пытаюсь решить SPOJ Проблема SUMFOUR .... Я адресность TLE на тестовом примере 9 http://www.spoj.com/problems/SUMFOUR/SPOJ SUMFOUR ..... TLE на тестовом примере 9

Итак, какая часть моего кода должен быть ? отредактирован и как здесь N = 4000 <

#include <iostream> 
#include<string> 
#include<algorithm> 
#include<cstdio> 
#include<cmath> 
#include<map> 
#include<vector> 

using namespace std; 


int main() 
{ 
int a[4005][5],n; 
cin>>n; 
for(int i=1;i<=n;i++) 
    for(int j=1;j<=4;j++) 
     scanf("%d",&a[i][j]); 
int k=0; 
for(int i=1;i<=n;i++) 
{ int p=a[i][1]; 
    for(int j=1;j<=n;j++) 
    { b.push_back(p+a[j][2]); 
     k++; 
    } 
} 
k=0; 
for(int i=1;i<=n;i++) 
{ int p=a[i][3]; 
    for(int j=1;j<=n;j++) 
    { c.push_back(p+a[j][4]); 
     k++; 
    } 
} 
sort(b.begin(),b.end()); 
int cnt=0; 
for(int j=0;j<k;j++) 
    if(find(b.begin(),b.end(),-c[j])!=b.end()) 
     cnt=cnt+count(b.begin(),b.end(),-c[j]) ; 


printf("%d\n",cnt); 
return 0; 
} 
+1

Если вы пишете код на C++, используйте индексы стиля C++ от 0 до n - 1 для ваших векторов. Это 'for (int i = 1; i <= n; i ++)' неудобно смотреть. –

+0

1) пожалуйста, последовательно укажите код для удобочитаемости человека. предложите 4 пробела после каждой открытой скобки '{' и un-indent перед каждой закрывающей скобкой '}'. Обратите внимание, что из-за разных сред есть разные табуляции/ширина, никогда не используя вкладки для отступов. 2) используйте пустую строку для смещения блоков кода для удобочитаемости.3) при запросе пользовательского ввода (cin >> n) всегда префикс с подсказкой cout << "для конкретного ввода" << cend, чтобы пользователь не оставил пустой экран, мигающий курсор и не знал, что делать дальше – user3629249

+0

1) зачем смешивать 'cin' и 'scanf()'? 2) действительно ли вы ожидаете, что пользователь будет вводить до 16000 целых значений? 3) всегда проверяйте возвращаемое значение из scanf(), а не значения параметра, чтобы убедиться, что операция прошла успешно. – user3629249

ответ

2

проблема здесь:

for(int j=0;j<k;j++) 
     if(find(b.begin(),b.end(),-c[j])!=b.end()) 
      cnt=cnt+count(b.begin(),b.end(),-c[j]) ; 

при п = 4000, так что есть 4000^2 элементов в Ь и с. Таким образом, временная сложность этого цикла составляет 4000^4, так как find и count сложность времени - O (n), что, конечно же, приведет к превышению лимита времени.

Итак, как вы можете сократить время? Вы можете использовать двоичный поиск , чтобы ускорить процесс подсчета, что уменьшает временную сложность вышеуказанного цикла до O (n^2 log n), так как я заметил, что вы уже сортируете b.

Или вы можете использовать map для подсчета и сохранения частоты каждого элемента в b и c.

map<long long, int> b; 
map<long long, int> c; 

for(int i=1;i<=n;i++) 
{ long long p=a[i][1]; 
    for(int j=1;j<=n;j++) 
    { 
     long long tmp =p + a[j][2]; 
     b[tmp] = b[tmp] + 1; 
    } 
} 
// Similar for c 
map <long long, int>::iterator it; 
long long result; 
for (it = c.begin(); it != c.end(); ++it) 
     result += c[it->first]*b[-(it->first)]; 

Для вашего нового обновления, пожалуйста, изменить:

for(int j=1;j<=n;j++) 
    { if(b.count(a[i][1]+a[j][2])) 
     { b[a[i][1]+a[j][2]]+=1; 
      c[a[i][3]+a[j][4]]+=1; 
     } 
     else 
     { b[a[i][1]+a[j][2]]=1; 
      c[a[i][3]+a[j][4]]=1; 
     } 
    } 

в этом:

for(int j=1;j<=n;j++) 
    { 
      b[a[i][1]+a[j][2]]+=1; 
      c[a[i][3]+a[j][4]]+=1;    
    } 

условие проверки if(b.count(a[i][1]+a[j][2])) является только b, и использовать его для c, который Сделайте c некорректным.

Обновление: После попытки принять в SPOJ, оказывается, что карта не достаточно быстро, поэтому я вношу изменения в двоичный поиск и принимаю.

Мои accepted code

+0

Давайте продолжим обсуждение в чате (http://chat.stackoverflow.com/rooms/79773/discussion-between-rsd-unleashed-and-pham-trung). –

+0

@PhamTrung: Вернулся назад к оригинальному вопросу, чтобы сделать ваш ответ действительным ..... –

+0

@rsd_unleashed см. Мое обновление! –

0

Пожалуйста, не используйте карту в качестве худшего случая сложности может быть O (журнал (п)).

SO Вместо этого вы можете просто использовать два отсортированных массива и для каждого элемента, как в

первого массива, Двоичный поиск своего -ve агента во второй накопительном массиве.

Просто измените метод поиска в последних строках на двоичный поиск (c.begin(), c.end(), key) и найдите repititons до конца с этим индексом, поскольку он дает индекс lower_bound.

Это Общая сумма дает ответ и ожидаемый Сложность

О (п^2log (п)).

Смежные вопросы