codeforces 1019 A. Elections (枚举或三分)

链接

这里写图片描述

昨天CF的题,没想到自己会做的这么傻逼。。。真菜啊

题意:就N个选民,M个政党。已知每个选民原本打算投给的政党,已经收买他们的价格,问你花费最少的价格,使得1号政党的票数最多。

思路:直接考虑政党的得票数,使得1号政党高于这个票数,其他政党低于这个票数就行了。(1号政党可以远远高于这个得票数,但其他政党必须低于这个票数)然后从1到N枚举这个票数,维护最小值就行了。只要统计每个政党的得票数,那数据按收买价格从小到大排序就行了,对于高于这个票数的政党,就直接收买选民,知道不高于为止,如果到最后1号政党的票数还是低于枚举的票数,那么就从小到大再扫描一遍,只有是没被收买的都收买掉,直到达到为止。

这是O(N^2)的做法,不过我们可以考虑这样一件事,最小值一定出现在[1,N]这个区间,所如果画出花费金额和枚举的得票数就会发现这是一个凹函数,存在极小值。
这里写图片描述

所以我们可以三分求一下这个凹函数的极小值。
不理解三分的可以看下这个博客:https://blog.csdn.net/qq_34374664/article/details/70141246

这样我们就可以把时间复杂度降为O(NlogN)的了。

枚举代码如下:

#include<bits/stdc++.h>

using namespace std;
const int MAX = 3010;
typedef long long ll;
int N,M;
class Node{
public:
    int p;
    ll c;
};
Node q[MAX];
bool operator < (Node A,Node B){
    return A.c < B.c;
}
int num[MAX],now[MAX];
bool book[MAX];
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值