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;//圆满结束
}

马蜂不好,勿喷

据说多倍经验,写一下:

CF1251E2

P6346

posted @ 2025-03-04 20:38  M_CI  阅读(25)  评论(0)    收藏  举报