jiejiejiang2004

题解:CodeForces 1019 A Elections[贪心/三分]

CodeForces 1019A

A. Elections

time limit per test: 2 seconds
memory limit per test: 256 megabytes
input: standard input
output: standard output

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 — \(n\) and \(m\) 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 \(i\)-th voter \(c_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.

Input

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

Each of the following \(n\) lines contains two integers \(p_i\) and \(c_i\) (\(1 \le p_i \le m\), \(1 \le c_i \le 10^9\)) — 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 \(1\).

Output

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

Examples

input

1 2
1 100

output

0

input

5 5
2 100
3 200
4 300
5 400
5 900

output

500

input

5 5
2 100
3 200
4 300
5 800
5 900

output

600

这题有两种解法

第一种解法:贪心暴搜

根据题意,一共有N票,M个候选人
数据范围是[1,3000],比较小,可以暴搜
先要把每一票记录下来,按花费从小到大排序
我们假设最终每个候选人不超过k票,而我们的目标(1号候选人)至少要有k票
把达成这个目标的成本记录下来,从1到N遍历求最小值就好了(我尝试过N/2也能过,差异不大)
那么这个计算的过程是这样的:
按花钱从小到大的顺序遍历,
假如说这票是1号的,就跳过
假如说这个投票人投票的对象的票数 < k,暂且跳过
假如说这个投票人投票的对象的票数 > k,那就把这票抢过来
如果完成上面三个过程之后,1号的票数还是 < k,那就按照花费从小到大的顺序,还没抢过来的就抢过来,直到 ≥ k 为止。

第二种解法:三分

在用三分解决这道题目之前,首先你要了解什么是三分(不知道就点这里)
剩下的就很简单了,这个图像可以近似看成一个方向向下的凹函数,套上板子就好了

我的代码

#include <bits/stdc++.h>
#define int long long

struct node{
	int peo,cost;
	bool operator < (const node &a){
		return this->cost < a.cost;
	}
};

int n,m;
const int N = 3010;
node inp[N];
std::vector<int> num(N);

int check(int max_c)
{
	int ans = 0;
	bool book[N];
	std::vector<int> p(num);
	for(int i = 0 ; i < n ; i ++)
	{
		if(inp[i].peo == 1) book[i] = true;
		else if(p[inp[i].peo] < max_c) book[i] = false;
		else
		{
			book[i] = true;
			p[1] ++;
			p[inp[i].peo] --;
			ans += inp[i].cost;
		}
	}
	

	for(int i = 0 ; i < n && p[1] < max_c; i ++)
	{
		if(book[i] == true) continue;
		else
		{
			p[1]++;
			ans += inp[i].cost;	
		}
	}
	
	return ans;
}


signed main()
{
	std::cin >> n >> m;
	for(int i = 0 ; i < n ; i ++)
	{
		std::cin >> inp[i].peo >> inp[i].cost;
		num[inp[i].peo]++;
	}
	std::sort(inp,inp + n);
	
//贪心暴搜代码 
	/*	
	int ans = check(1);
	for(int i = 2 ; i <= N/2 + N%2 ; i ++)
	{
		ans = std::min(ans,check(i));
	}
	
	std::cout << ans;
	*/
	
//三分代码	
	int l=0,r=n-1;
	while(l < r-1)
	{
		int mid = l + r >> 1;
		int mmid = r + mid >> 1;
		if(check(mid) > check(mmid))
			l = mid;
		else
			r = mmid;
	}
	
	std::cout << std::min(check(l),check(r));
	return 0;
}

PS:

思路参考:(大佬链接指路)



有什么出现纰漏的地方还请大家在评论区指出!谢谢!

posted on 2024-07-14 13:56  Jiejiejiang  阅读(5)  评论(0编辑  收藏  举报

导航