SPOJ - Kolejka

0

Witam,
od niedawna stawiam swoje pierwsze kroki w C++ (w ogóle w programowaniu) i napotkałem na problem z jednym z zadań na SPOJ-u. Mianowicie, chodzi o to zadanie: http://pl.spoj.com/problems/AL_01_02/
Problem udało mi się rozwiązać (a przynajmniej tak mi się wydawało). Program działał w każdym przypadku, cokolwiek bym mu nie podał, nie wyrzucał żadnych błędów ani wyjątków. Kiedy jadnak wrzucam mój kod na SPOJ-a, to otrzymuję komunikat o przekroczeniu limitu czasu (co jest dziwne, bo na moim komputerze niezależnie od ilości podanych znaków (oczywiście mieszczących się w zakresie zadania) program wykonuje tę operacje w znacznie mniej niż 1s). Oto mój kod:

#include <iostream>
#include <string>
#include <cstring>
#include <list>

using namespace std;

long int t;
string kolejka;

void kolejkaFinal(char *cstr) {
  list <char> mylist;
  list<char>::iterator it1, it2, it3;
  for (int i=0; i<kolejka.size(); i++) {
    mylist.push_back(cstr[i]);
  }
  for (int i=0; i<kolejka.size(); i++) {
    it1=it2=mylist.begin();
    advance(it2, 1);
    while (it2!=mylist.end()) {
      if (*it1<*it2) {
        it1=mylist.erase(it1);
      }
      else {
        it1++;
        it2++;
      }
    }
  }
  for (it3=mylist.begin(); it3!=mylist.end(); it3++) {
    cout << *it3;
  }
}

int main() {
  cin >> t;
  for (long int i=0; i<t; i++) {
    cin >> kolejka;
    char cstr[kolejka.size()+1];
    strcpy(cstr, kolejka.c_str());
    kolejkaFinal(cstr);
  }
  return 0;
}

Czy jest tutaj coś, co może powodować takie zachowanie algorytmu sprawdzającego na SPOJ-u, jakiś błąd lub coś co dałoby się usprawnić?

Jeśli ktoś przeczytał to w całości, to z góry dziekuję za poświęcony czas.

0

Zgaduję, ale prawie na pewno padasz na próbie wczytania całego wiersza od razu. Zwróć uwagę, że zgodnie ze specyfikacją zadania pojedynczy wiersz może mieć nawet 10^6 znaków (czyli ~1MB(thx za zwrócenie uwagi...)) ! Po wczytaniu ten napis kopiujesz do tablicy znakowej (po co ?) a potem dopiero przekazujesz do funkcji.

Potem w funkcji kopiujesz po kolei wczytane znaki z oryginalnego string-a do listy - masz już 3 razy to samo !

0

Co masz na myśli mówiąc, że padam na próbie wczytania całego wiersza? SPOJ wyrzuca przekroczenie limitu czasu, nie pamięci. Poza tym wydaje mi się, że SPOJ próbuje podać ciąg znaków na raz, tak jak jest to przedstawione w przykładzie.
Poprawiłem też to wczytywanie znaków, już nie ma kopiowania dwa razy do różnych pojemników:

#include <iostream>
#include <list>

using namespace std;

long int t;
char x;

list <char> mylist;
list<char>::iterator it1, it2, it3;

int main() {
  cin >> t;
  for (long int i=0; i<t; i++) {
    while (cin >> x) {
      mylist.push_back(x);
    }
    int list_size=mylist.size();
    for (int i=0; i<list_size; i++) {
      it1=it2=mylist.begin();
      advance(it2, 1);
      while (it2!=mylist.end()) {
        if (*it1<*it2) {
          it1=mylist.erase(it1);
        }
        else {
          it1++;
          it2++;
        }
      }
    }
    for (it3=mylist.begin(); it3!=mylist.end(); it3++) {
      std::cout << *it3;
    }
  }
  return 0;
}

Tylko teraz program zajmuje jeszcze więcej pamięci niż przedtem. Wiesz może czemu?

2

A nie szybciej będzie jak zamiast trzymać to wszystko w liście, wczytasz literę i od razu ustawisz na odpowiednim miejscu w kolejce? W zadaniach ze spoja jest tak że wejście się "chomikuje" w tablicach, listach, etc tylko jak jest to niezbędne (bo będą ci potrzebne więcej niż raz). A w tym zadaniu niczego takiego NIE MA.

1 użytkowników online, w tym zalogowanych: 0, gości: 1