题目大意:有$n$个人,$m$个政党,每个人都想投一个政党,但可以用一定的钱让他选你想让他选的政党。 现在要$1$号政党获胜,获胜的条件是:票数严格大于其他所有政党。求最小代价
题解:暴力枚举其他政党的最多得票,然后把超过的贪心收买,若$1$号政党得票不够,就继续贪心收买,更新答案,复杂度$O(n^2 log_2 n)$($n=3000,time;limit=2s$卡过)
卡点:1.用$pb\_ds$的$priority\_queueTIL$,换成$std:priority\_queueAC$
C++ Code:
#include <cstdio> #include <ext/pb_ds/priority_queue.hpp> #define int long long #define maxn 3010 using namespace std; int n, m, ans = 0x3f3f3f3f3f3f3f3f; int p[maxn], c[maxn]; struct cmp { inline bool operator ()(int a, int b) {return a > b;} }; //__gnu_pbds::priority_queue<int, cmp, __gnu_pbds::binary_heap_tag> q[maxn], Q; priority_queue<int, std::vector<int>, cmp > q[3050], Q; void solve(int mid) { for (int i = 1; i <= m; i++) while (!q[i].empty()) q[i].pop(); for (int i = 1; i <= n; i++) q[p[i]].push(c[i]); int res = 0, sz = q[1].size(); for (int i = 2; i <= m; i++) { while (q[i].size() > mid) { res += q[i].top(); q[i].pop(); sz++; } } if (sz <= mid) { int delta = mid - sz + 1; while (!Q.empty()) Q.pop(); for (int i = 2; i <= m; i++) { int tmp = 0; while (!q[i].empty() && tmp < delta) { Q.push(q[i].top()); q[i].pop(); tmp++; } } while (sz <= mid && !Q.empty()) { res += Q.top(); Q.pop(); sz++; } } if (res < ans) ans = res; } signed main() { scanf("%I64d%I64d", &n, &m); for (int i = 1; i <= n; i++) { scanf("%I64d%I64d", &p[i], &c[i]); } for (int i = n - 1; ~i; i--) solve(i); printf("%I64d ", ans); return 0; }