CF1019A Elections

CF1019A Elections

洛谷传送门

题目描述

As you know, majority of students and teachers of Summer Informatics School live in Berland for the most part of the year. Since corruption there is quite widespread, the following story is not uncommon.

Elections are coming. You know the number of voters and the number of parties — nn and mm respectively. For each voter you know the party he is going to vote for. However, he can easily change his vote given a certain amount of money. In particular, if you give ii -th voter c_ic**i bytecoins you can ask him to vote for any other party you choose.

The United Party of Berland has decided to perform a statistical study — you need to calculate the minimum number of bytecoins the Party needs to spend to ensure its victory. In order for a party to win the elections, it needs to receive strictly more votes than any other party.

输入格式

The first line of input contains two integers nn and mm ( 1 le n, m le 30001≤n,m≤3000 ) — the number of voters and the number of parties respectively.

Each of the following nn lines contains two integers p_ip**i and c_ic**i ( 1 le p_i le m1≤p**im , 1 le c_i le 10^91≤c**i≤109 ) — the index of this voter's preferred party and the number of bytecoins needed for him to reconsider his decision.

The United Party of Berland has the index 11 .

输出格式

Print a single number — the minimum number of bytecoins needed for The United Party of Berland to win the elections.

题意翻译

Berland地区的腐败现象非常常见。

马上有一场选举,你事先知道了选民和政党的数量,分别为 nn 和 mm ,对于每一位选民,你知道他将要选举哪一个政党,不过,每一位选民都会在接受一定数额的金钱之后改变他的主意。如果你给第 ii 位选民 c_ic**i 数额的比特币,他就会选举任何你希望他选举的政党。

你的目的是让Berland的联合党赢得这场选举,联合党必须拥有比其它政党都多的选票,在此基础之上,你希望花费的比特币尽可能少。

输入格式

第一行包含两个整数 nn 和 mm .

接下来 nn 行每一行两个整数—— p_ip**i 和 c_ic**i ,这一位选民将会选举政党的编号,和使他改变主意的最少比特币数额。

特别地,联合党的编号是1.

输出格式

一个整数,使联合党赢得选举所需花费的最少比特币数额。


题解:

一眼看出来贪心。

数据范围300,可以随便搞。N^2预定。

咋贪呢?发现如果正向考虑买票,并不是买价格最小的选民就最优,因为其他党派比你票多,如果你在削弱大党的同时给自己买票,有可能会更优。

所以考虑逆向贪心。

直接枚举自己最终胜选的票数是多少票,假设是(x)张。然后显然,高于这些票数的党派都需要被砍成(x-1)张才能保证让联合党胜出。在砍这些党派的过程中,肯定要从小到大买。

在砍完这些党派之后,如果1党还是没有等于x,那只好从剩下的所有党派中从小到大买。

然后发现这整个算法流程就是一枚举+判断。

所以完全可以用二分进行优化,把N优化成logN。

代码:

#include<cstdio>
#include<vector>
#include<algorithm>
#define ll long long
using namespace std;
const int maxn=3003;
int n,m;
vector<int> v[maxn];
ll check(int x)//买x张选票能否更优
{
	ll ret=0;
	int tot=0;
	vector<int> tmp;
	for(int i=1;i<=m;++i)
	{
		int j=0,k=v[i].size();
		while(k>=x) 
			ret+=v[i][j++],--k,++tot;
		while(j<v[i].size()) 
			tmp.push_back(v[i][j++]);
	}
	sort(tmp.begin(),tmp.end());
	for(int i=0;i<tmp.size();++i)
	{
		if(tot>=x) 
			break;
		ret+=tmp[i],++tot;
	}
	return ret;
}
int main()
{
	scanf("%d%d",&n,&m);
	for(int i=1;i<=n;i++)
	{
		int p,c;
		scanf("%d%d",&p,&c);
		v[p].push_back(c);
	}
	for(int i=1;i<=m;i++)
		sort(v[i].begin(),v[i].end());
	for(int i=0;i<v[1].size();i++)
		v[1][i]=0;
	int l=1,r=n;
	while(l<=r)
	{
		int mid=(l+r)>>1;
		if(check(mid)<check(mid+1))
			r=mid-1;
		else
			l=mid+1;
	}
	printf("%lld
",check(l));
	return 0;
}
原文地址:https://www.cnblogs.com/fusiwei/p/13998463.html