1


First I would like to say, that C++ is not my basic language, and I ask for forgiveness if it's basic knowledge.
My problem is that I have to overcome spoj time limit with my algorithm. I am confident that algorithm itself is good (and I dont't want help with it ;) ), but data passed to it is given from console.
I need to read random number of integers (limit is 10^7) in single line terminated by EOF symbol. So far I got something like that:

cin.tie(NULL);
std::ios::sync_with_stdio(false);

vector <unsigned int > vector_of_int;

...

std::string str;
std::getline(std::cin, str);
std::istringstream sstr(str);
unsigned int n;

while(sstr >> n){
    vector_of_int.push_back(n); 
}

However - this is not fast enough to fit in time limit for this task. So question is - is there any faster (spoj-friendly) way to read this kind of data?

My results are

number      status  signal  time    memory
test 0      passed  OK      0.0s    2828KB
test 1      passed  OK      0.0s    2828KB
test 2      passed  OK      0.01s   2828KB
test 3      passed  OK      0.0s    2828KB
test 4      passed  OK      0.01s   2828KB
test 5      passed  OK      0.0s    2828KB
test 6      passed  OK      0.0s    2940KB
test 7      passed  OK      0.04s   3060KB
test 8      passed  OK      0.24s   3452KB
test 9      passed  OK      0.44s   3452KB
test 10     passed  OK      0.84s   3452KB
test 11     TLE     OK      1.01s   27784KB
test 12     TLE     OK      1.01s   28056KB



EDIT:
Results after commenting vector_of_int.push_back(n); line

number  status          signal  time    memory
test 0  passed          OK      0.0s    2828KB
test 1  wrong answer    OK      0.0s    2828KB
test 2  wrong answer    OK      0.0s    2828KB
test 3  wrong answer    OK      0.0s    2828KB
test 4  wrong answer    OK      0.0s    2828KB
test 5  wrong answer    OK      0.0s    2828KB
test 6  wrong answer    OK      0.01s   2964KB
test 7  runtime error   SIGSEGV 0.02s   3128KB
test 8  runtime error   SIGSEGV 0.06s   5504KB
test 9  runtime error   SIGSEGV 0.09s   8032KB
test 10 runtime error   SIGSEGV 0.16s   13224KB
test 11 runtime error   SIGSEGV 0.21s   14976KB
test 12 runtime error   SIGSEGV 0.28s   23440KB



EDIT 2:
I've noticed that input line is terminated by EOF instead of new line.

  • How close are you to the time limit? i.e. do we have to bin the whole approach or could we tweak it? – Bathsheba Mar 25 '15 at 10:14
  • Does it HAVE to come from the console? File would be better. Can you wait to start the benchmark until after you've loaded your inputs? Also, you should definitely at least add timer code inside this program (or run a profiler) to diagnose if this is even your bottleneck. – VoidStar Mar 25 '15 at 10:17
  • @VoidStar: I wish I could start benchmark after that ;) I have tested it on my machine and complexity of algorithm seems ok, when performed on data not readed from console. – Kuba Łapuszyński Mar 25 '15 at 10:25
  • I suspect it's down to the way the OS is pumping the console input to your app. If you're lucky, it *might* be the `push_back`. Trival to eliminate that possibility: comment the line and retest. – Bathsheba Mar 25 '15 at 10:28
  • @Bathsheba - I have commented 'vector_of_int.push_back(n);' line - results in post. However - I need that line to calculate results later ;) – Kuba Łapuszyński Mar 25 '15 at 10:53

2 Answers2

1

Given the results data, I believe you can come in under target by including the line

vector_of_int.reserve(1e7);

before calling any push_back.

This line tells the vector to reserve memory for receiving at least 1e7 elements. This will prevent any memory reallocation which seems to be currently happening. 1e7 is clearly documented in your question as the upper limit.

Bathsheba
  • 231,907
  • 34
  • 361
  • 483
0

I have found solution!

vector <int> vector_of_int;
vector_of_int.reserve(1e7);

char ch;
int i = 0;
int acc = 0, buf;

while( (ch=getchar()) > 0 ){
    if(ch!=' ') {
        acc = acc * 10 + ch - '0';
    } else {
        vector_of_int.push_back(acc);
        acc = 0;
    }
}

It gave me results listed below

number  status  signal  time    memory
test 0  passed  OK      0.0s    2688KB
test 1  passed  OK      0.01s   2688KB
test 2  passed  OK      0.01s   2688KB
test 3  passed  OK      0.01s   2688KB
test 4  passed  OK      0.01s   2688KB
test 5  passed  OK      0.01s   2688KB
test 6  passed  OK      0.01s   2688KB
test 7  passed  OK      0.01s   2688KB
test 8  passed  OK      0.12s   2688KB
test 9  passed  OK      0.23s   2688KB
test 10 passed  OK      0.46s   2688KB
test 11 passed  OK      0.63s   2688KB
test 12 passed  OK      0.86s   2688KB

I haven't change a single line in algorithm, so that made the trick.