#include using namespace std; struct Rows { // we represent width of rows as // extra[height] + pad_c + height * pad_h // where height is zero-based uint64_t pad_c; uint64_t pad_h; vector extra; Rows() { pad_c = 0; pad_h = 0; extra = {1}; cerr << "height " << 1 << " val " << 1 << "\n"; cout << 1 << "\n"; } uint64_t height() const { return extra.size(); } uint64_t width(const uint64_t &h) const { if (h >= extra.size()) { return 0; } return pad_c + pad_h * h + extra[h]; } void add_one(uint64_t n) { // basic addition of new brick if (n <= width(height()-1)) { extra.push_back(n - pad_c - pad_h * height()); cerr << "height " << height() << " val " << n << "\n"; cout << n << "\n"; return; } for (int64_t i = height()-1; i >= 0; i--) { if (i == 0 || width(i) + n <= width(i-1)) { extra[i] += n; return; } } } void add_stairs(uint64_t n) { // add stairs of bricks, // one per each height, // starting from 0 and // adding a new block on top pad_c += n; pad_h += 1; uint64_t n_top = n + height(); extra.push_back(n_top - pad_c - pad_h * height()); cerr << "height " << height() << " val " << n_top << "\n"; cout << n_top << "\n"; } uint64_t min_step() const { // how many stairs we can add? // depends on the minimum width difference between adjacent rows // because when we add [n] to a row, // we surely can not put [n+1] higher than on top of the added [n] brick // and that is possible exactly when the difference between the widths is nonzero uint64_t res = width(height()-1); for (int64_t i = height()-1; i > 0; i--) { res = min(res, width(i-1) - width(i)); } return res; } }; int main() { Rows rows; uint64_t n = 2; while (1) { uint64_t step = rows.min_step(); // step > 0 ensures that we can add full stairs (see min_step()) // step < n ensures that we can not put [n] on top of some brick // (has to start on the floor) if (0 < step && step < n) { for (uint64_t i = 0; i < step; i++) { rows.add_stairs(n); n += rows.height(); } } else { rows.add_one(n); n++; } } return 0; }