Pranav_20's blog

By Pranav_20, 15 months ago, In English

I was solving this problem, this was the code that I wrote initially in which I used vector for dp (CODE), but when I replaced it with a global array of the same size it got AC (Updated Code), Can anyone please explain what is the problem with using vector here, or an article which explains this would be helpful.

Thnaks!

  • Vote: I like it
  • +5
  • Vote: I do not like it

»
15 months ago, # |
Rev. 2   Vote: I like it 0 Vote: I do not like it

vector is (data address, actual size, allocated size) + allocated items

There we assume sizeof(int) == 4, sizeof(size_t) == sizeof(pointer) == 8

vector<int> with actual size == allocated size == 2 takes 8 * 3 + 2 * 4 = 32 bytes
vector<vector<int>> 5000x2 takes 8 * 3 + 5000 * 32 = 160024 bytes
vector<vector<vector<int>>> 5000x5000x2 takes 8 * 3 + 5000 * 160024 = 800120024 bytes

800120024 bytes ~ 781367 kilobytes ~ 763 megabytes

int dp[5002][5002][2] is just 5002 * 5002 * 2 * 4 bytes = 200160032 bytes ~ 195469 kilobytes ~ 191 megabytes

Pretty easy math tells that vector 2x5000x5000 instead of 5000x5000x2 would take somewhat about 191 megabytes too.

  • »
    »
    15 months ago, # ^ |
      Vote: I like it +10 Vote: I do not like it

    Some extra details.

    Creating a lot of small vectors is bad, but the size of the innermost vector is fixed in compile-time, so you can use std::array<int, 2>, which takes exactly 8 bytes. So the dp type will be vector<vector<array<int, 2>>> and it passes easily: 219843927

    Funny enough, if you just use a 2x5000x5000 vector, you will still get ML: 219843261 (extra points for guessing why :).

    • »
      »
      »
      15 months ago, # ^ |
        Vote: I like it +10 Vote: I do not like it

      Because inner 5000×5000 vector as temporary argument for construction itself takes ~90 megabytes, so for creation there is need something about 292 megabytes.

      I guess, that something like

      vector<vector<vector<int>>> v(2);
      for (int i = 0; i < 2; ++i) {
          v[i].resize(n + 2);
          for (int j = 0; j < n + 2; ++j) {
             v[i][j].assign(n + 2, -1);
          }
      }
      

      will work (can't check now)

    • »
      »
      »
      15 months ago, # ^ |
      Rev. 2   Vote: I like it +5 Vote: I do not like it

      Got it, creating a lot of small vectors is really bad, as balalaika calculated above it uses 800120024 bytes. whereas if we use vector<vector<array<int,2>>> —

      • array<int,2> will use exactly 8 bytes.
      • vector<array<int,2>> => 24 + 5000*8 = 40024 (here itself it made a huge optimization in memory because we used 8 bytes instead of 32 bytes)
      • vector<vector<array<int,2>> => 24 + 5000 * 40024 = 20,01,20,000 ~ 200 MB So, that's why vector<vector<vector>> is giving MLE and vector<vector<array<int,2>>> is not.