CF EDU 117 E - Messages
阿新 • • 發佈:2022-05-12
E - Messages
思維
因為每個學生最多隻能讀 k (1 <= k <= 20) 條訊息,可以從這個小資料入手
結論:最多貼 20 條訊息
可以算出貼 t 條訊息時,貼每條訊息的貢獻,取最大的 t 個貢獻相加, 設貢獻分別為期望 \(a_i\) 個學生能讀到
若已經貼了貢獻最大的 20 條,再貼一條時,相當於 \(+\frac {20}{21} *a_{21}-\frac {1}{21} * \sum\limits_{i=1}^{20} a_i\), 因為 \(a_i\) 單調遞減,所以這個數一定<=0,所以貼 20 條以上沒有意義
列舉貼多少條算貢獻即可
\(O(n*logn+20*n*log20)\)
#include <iostream> #include <cstring> #include <algorithm> #include <vector> #include <cmath> #include <map> #include <queue> using namespace std; typedef long long ll; typedef pair<double, int> PDI; const int N = 2e5 + 10; int n; int m[N], k[N]; map<int, vector<int> > mp; int main() { ios::sync_with_stdio(false), cin.tie(0), cout.tie(0); cin >> n; for (int i = 1; i <= n; i++) { cin >> m[i] >> k[i]; mp[m[i]].push_back(k[i]); } int cnt = 0; double maxn = 0; int ans[30]; for (int t = 1; t <= min(20, (int)mp.size()); t++) //釘 t 個資訊 { double now = 0; priority_queue<PDI> heap; for (auto [id, vt] : mp) //釘這條資訊的貢獻 { double add = 0; for (auto i : vt) //哪些人要看這條資訊 { if (i >= t) { add += 1; } else { add += (double)i / t; } } heap.push({add, id}); } int tmp[30]; for (int i = 1; i <= t; i++) { now += heap.top().first; tmp[i] = heap.top().second; heap.pop(); } if (now > maxn) { maxn = now; cnt = t; memcpy(ans, tmp, sizeof ans); } } cout << cnt << endl; for (int i = 1; i <= cnt; i++) cout << ans[i] << " "; cout << endl; return 0; }