#include using namespace std; typedef long long ll; const ll INF = 4e18; int main() { ios::sync_with_stdio(false); cin.tie(nullptr); int N; cin >> N; vector c(N + 1); vector v(N + 1); for (int i = 1; i <= N; ++i) { cin >> c[i] >> v[i]; } // 重量 >= 2 的物品最多选 N/2 个 int MAX_M = N / 2 + 1; vector> dp(MAX_M, vector(N + 1, -INF)); dp[0][0] = 0; vector A(MAX_M, -INF), B(MAX_M, -INF); // 处理重量 >= 2 的物品 for (int i = 2; i <= N; ++i) { if (c[i] == 0) continue; // 按 d = w - i*m 分组 for (int d = -N; d <= N; ++d) { // 计算有效的 m 范围 int m_min; if (d >= 0) m_min = 0; else m_min = (-d + i - 1) / i; m_min = max(m_min, 0); int m_max; if (N - d < 0) m_max = -1; else m_max = (N - d) / i; m_max = min(m_max, MAX_M - 1); if (m_min > m_max) continue; // 提取当前 d 对应的一维数组 for (int m = m_min; m <= m_max; ++m) { int w = d + i * m; A[m] = dp[m][w]; } // 一维多重背包(物品重量为 1,价值为 v[i],数量为 c[i]) deque q; for (int m = m_min; m <= m_max; ++m) { if (A[m] != -INF) { ll val = A[m] - (ll)m * v[i]; while (!q.empty() && (A[q.back()] - (ll)q.back() * v[i]) <= val) { q.pop_back(); } q.push_back(m); } while (!q.empty() && q.front() < m - c[i]) { q.pop_front(); } if (!q.empty()) { int k = q.front(); B[m] = A[k] + (ll)(m - k) * v[i]; } else { B[m] = -INF; } } // 写回 dp for (int m = m_min; m <= m_max; ++m) { int w = d + i * m; dp[m][w] = B[m]; } } } // 合并重量为 1 的物品 ll v1 = v[1]; // pref[m][W] = max_{w <= W} (dp[m][w] - m * v1) vector> pref(MAX_M, vector(N + 1, -INF)); for (int m = 0; m < MAX_M; ++m) { ll cur_max = -INF; for (int w = 0; w <= N; ++w) { if (dp[m][w] != -INF) { ll val = dp[m][w] - (ll)m * v1; if (val > cur_max) cur_max = val; } pref[m][w] = cur_max; } } // 计算每个 k 的答案 for (int k = 1; k <= N; ++k) { ll ans = -INF; int max_m = min(k, MAX_M - 1); for (int m = 0; m <= max_m; ++m) { int W = N - k + m; if (W >= 0 && W <= N) { if (pref[m][W] != -INF) { ll val = pref[m][W] + (ll)k * v1; if (val > ans) ans = val; } } } cout << ans << '\n'; } return 0; }