Actually, your code is already pretty much memory optimized as it is.
You allocate a 1000 64-bit pointers in your first line. That's unavoidable since that is what your machine uses. However, that only takes 8000 bytes, hardly worth the effort optimizing these days.
In the next lines, you dynamically allocate space for int32_t arrays, which only take 4 bytes per entry. So if you allocate 30 million entries, it will take 120.000.000 bytes. I think you are mistaken in thinking that this secondary array will take 30 million * 8 bytes = 240.000.000 bytes, which it doesn't. Only the pointer is 64 bit, the data itself will take up as much or as little space as it needs.
Addendum: I want to add that allocating a two dimensional array, as some have suggested, will actually waste more memory, since your clearly don't know how long each secondary entry will be. Your solution allocates only as much space as needed.