zoukankan      html  css  js  c++  java
  • CF457C Elections

    CF457C Elections

    洛谷传送门

    题目描述

    You are running for a governor in a small city in Russia. You ran some polls and did some research, and for every person in the city you know whom he will vote for, and how much it will cost to bribe that person to vote for you instead of whomever he wants to vote for right now. You are curious, what is the smallest amount of money you need to spend on bribing to win the elections. To win elections you need to have strictly more votes than any other candidate.

    输入格式

    First line contains one integer nn ( 1<=n<=10^{5}1<=n<=105 ) — number of voters in the city. Each of the next nn lines describes one voter and contains two integers a_{i}a**i and b_{i}b**i ( 0<=a_{i}<=10^{5}; 0<=b_{i}<=10^{4}0<=a**i<=105; 0<=b**i<=104 ) — number of the candidate that voter is going to vote for and amount of money you need to pay him to change his mind. You are the candidate 00 (so if a voter wants to vote for you, a_{i}a**i is equal to zero, in which case b_{i}b**i will also be equal to zero).

    输出格式

    Print one integer — smallest amount of money you need to spend to win the elections.


    题解:

    一眼看出来贪心。

    是CF1019A的加强版。

    CF1019A是N^2贪心就能过,这个必须加二分枚举。

    当然,贪心策略都是一样的。

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

    所以考虑逆向贪心。

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

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

    然后发现这整个算法流程就是一二分判断。

    代码:

    #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;
    }
    
  • 相关阅读:
    nlog学习使用
    浏览器缓存信息的清理
    安装Debugging Tools时出现错误Setup could not find the file WinSDK_amd64的处理
    双网卡下添加静态路由方法
    DELL T430进RAID的方式:, 硬盘损坏后的处理方式
    虚拟机: 虚拟机win7的激活方式(底层操作系统 为 win10) ===用windows loader
    联想 M415 I3-6100 CPU安装系统方法
    AOC 电视机T3212M 进入 工厂模式方法,修改开机启动方式
    使用WinNTSetup安装win10时提示efi part有红叉(win10安装UEFI系统安装)
    联想服务器thinkserver TS550 Raid5制作及winserver2012R2 安装过来
  • 原文地址:https://www.cnblogs.com/fusiwei/p/13998488.html
Copyright © 2011-2022 走看看