// NOTE: this implementation may contain errors ^^' // // solution in O(n*log(n)^2) + output complexity in O(w*n) // idee: // binary search over the number of lines (O(log(n))) // For a given number of lines m we want to calculate width[i] for // 0<=i using namespace std; #define all(x) begin(x), end(x) #define sz(x) (ll)(x).size() using ll = long long; using ld = long double; constexpr ll inf = 0x3FFFFFFFFFFF; struct entry { ll pos, width, ma, lazy; void update() { ma = max(ma, lazy); lazy = 0; } void apply(ll val) { lazy = max(val, lazy); } }; int h; vector tree; constexpr entry query_default = {-1, inf, 0, 0}; entry combine(entry a, entry b) { a.update(); b.update(); if (a.width+a.ma < b.width+b.ma) return a; else return b; } void init(ll n) { tree.assign(n, query_default); } pair query(int l, int r) { entry res = query_default; for (; l < r; l++) { res = combine(res, tree[l]); } return {res.pos, res.width + res.ma}; } void updateLength(int l, int r, ll length) { for (; l < r; l++) { tree[l].apply(length); } } void updateWidth(int i, ll width) { tree[i] = {i, width, 0}; } int main() { ios_base::sync_with_stdio(false); cin.tie(nullptr); ll n, w; cin >> n >> w; w++; vector in(n); for (ll i = 0; i < n; i++) cin >> in[i]; ll cols = 0; vector pref(n), width(n); init(n); auto solve = [&](ll m) { pref[0] = -1; width[0] = sz(in[0]) + 1; updateWidth(0, width[0]); for (ll i = 1; i < n; i++) { updateLength(0, i, sz(in[i]) + 1); if (i < m) { pref[i] = -1; width[i] = max(width[i - 1], sz(in[i]) + 1); } else { auto e = query(i-m, i); pref[i] = e.first; width[i] = e.second; } updateWidth(i, width[i]); } }; ll l = 0; ll r = n; while (l + 1 < r) { ll m = (l + r) / 2; solve(m); if (width.back() <= w) { r = m; } else { l = m; } } solve(r); vector last = {n-1}, col = {width.back()}; while (pref[last.back()] >= 0) { last.push_back(pref[last.back()]); ll tmp = width[last.back()]; col.back() -= tmp; col.push_back(tmp); } reverse(all(last)); reverse(all(col)); vector output(r); for (ll i = 0, j = 0; i < sz(last); i++) { for (ll k = 0; j <= last[i]; j++, k++) { output[k] += in[j]; } ll ma = 0; for (ll k = 0; k < r; k++) ma = max(ma, sz(output[k])); for (ll k = 0; k < r; k++) { while (sz(output[k]) <= ma) output[k].push_back(' '); } } cout << r << " " << sz(last) << endl; for (ll i = 0; i < sz(col); i++) { cout << col[i]-1; if (i + 1 < sz(col)) cout << " "; } cout << endl; for (auto e : output) { e.pop_back(); cout << e << endl; } }