CF1251E1 Voting (Easy Version) 蓝 题解
思路
一眼丁真,鉴定为贪心。
一开始想了个 \(O(t \times n^2)\) 的暴力贪心,但因为看错数据范围而打了个 \(O(t \times n \log_2 n)\) 的小根堆维护的贪心。
首先将所有人按 \(m_i\) 从小到大的顺序排序,再倒序循环枚举每个人,使得有更高金钱需求的人可以被“零元购”就获得支持。每次将排完序后的第 \(i\) 个人的 \(q_i\) 值存入小根堆,如果这个人的 \(m_i\) 大于可“零元购”获得支持的人数 \(n-size\),则将所求答案 \(ans\) 加上堆顶元素,然后弹出堆顶,视作已获得其支持。最后输出答案 \(ans\)。
如果不懂看代码。
代码(有注释)
#include <bits/stdc++.h>
using namespace std;
#define int long long
int t,n;//数据组数与人数
struct node {
int m,q;
bool operator < (const node &x) const {
return m<x.m;
}//重载运算符
} a[5010];//人
priority_queue<int,vector<int>,greater<int> > h;//定义小根堆
signed main () {
cin>> t;//输入数据组数
while (t--) {
cin>> n;
long long ans=0;//所求答案(即最小代价)
while (h.size ()) h.pop ();//多测记得清空
for (int i=1;i<=n;i++)
cin>> a[i].m>> a[i].q;//输入人
sort (a+1,a+n+1);//按mi排序
for (int i=n;i>=1;i--) {//逆序枚举
h.push (a[i].q);//压入堆
if (a[i].m>n-h.size ()) {//判断是否不符合条件
ans+=h.top ();//增加花销
h.pop ();//弹出
}
}
cout<< ans<< "\n";//输出
}
return 0;//圆满结束
}
马蜂不好,勿喷
据说多倍经验,写一下:

浙公网安备 33010602011771号