cf1612 E. Messages
作者:互联网
题意:
导师有 \(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 << ' ';
}
标签:le,20,int,Messages,cf1612,消息,ans,置顶 来源: https://www.cnblogs.com/wushansinger/p/16448876.html