题意:
导师有 \(n\) 个学生和多条消息,现可以置顶若干条消息,每个学生只会看被置顶的消息中的随机的 \(k_i\) 条。导师希望第 \(i\) 个学生看到编号为 \(m_i\) 的消息,问置顶哪些消息可以最大化看到该看的消息的学生的数量的期望
\(1\le n,m_i\le 2e5,1\le k_i\le 20\)
思路:
假设置顶 \(t\) 条消息。对每条消息 \(m'\),如果选它的话,贡献就是 \(\frac {\min\{t,k_i\}}{t}[m_i=m']\)。置顶贡献前 \(t\) 大的消息即可。
只需枚举 \(t\le 20\),因为 \(t>20\) 时分子一定是 \(k_i\),增大分母只会使答案变小
const signed N = 3 + 2e5; int n, m[N], k[N]; db ans[21]; vector<int> choose[21]; void sol() { cin >> n; for(int i = 1; i <= n; i++) cin >> m[i] >> k[i]; for(int t = 1; t <= min(n,20); t++) { vector<PII> f(N, {0,0}); //贡献,消息id for(int i = 1; i < N; i++) f[i].se = i; for(int i = 1; i <= n; i++) f[m[i]].fi += min(t, k[i]); sort(all(f), greater<PII>()); for(int i = 0; i < t; i++) ans[t] += (db)f[i].fi / t, choose[t].pb(f[i].se); } int t = max_element(ans + 1, ans + 1 + 20) - ans; cout << t << endl; for(int i : choose[t]) cout << i << ' '; }