思路
一眼丁真,鉴定为贪心。
一开始想了个 O ( t × n 2 ) O(t \times n^2) O(t×n2) 的暴力贪心,但因为看错数据范围而打了个 O ( t × n log 2 n ) O(t \times n \log_2 n) O(t×nlog2n) 的小根堆维护的贪心。
首先将所有人按 m i m_i mi 从小到大的顺序排序,再倒序循环枚举每个人,使得有更高金钱需求的人可以被“零元购”就获得支持。每次将排完序后的第 i i i 个人的 q i q_i qi 值存入小根堆,如果这个人的 m i m_i mi 大于可“零元购”获得支持的人数 n − s i z e n-size n−size,则将所求答案 a n s ans ans 加上堆顶元素,然后弹出堆顶,视作已获得其支持。最后输出答案 a n s 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;//圆满结束
}
马蜂不好,勿喷
据说多倍经验,写一下: