cf 1020 round 503(SIS div2) C. Elections

题意:给出n个人投票,开始每个人都有一个选好的人,如果我们要使它换票就必须支付他所给的价格,我们要使1号选手赢得比赛,问我们支付最少的钱是多少来使一号赢得胜利

思路: 我们考虑到纯贪心有太多种情况,题目所给的数据也是3000,说明我们可以使用n^2以至更高的算法,我们考虑1号选手获胜的状态,就是他是以几票来获得胜利的

枚举获胜状态,然后我们取最优的

给一个例子    1:0票        2:3票          3:3票       4:2票         5 :1票

1号选手1票获取胜利   不存在

2票获取胜利     不存在

3票获取胜利     如果我们要三票赢2号和3号,必须要比2号3号多一票才可以,但是我们总共只买三票,既然我们不能增多自己,只能削弱对手,

其中一票在2号这里买,那么他就会降为2票,3号同理,然后剩下一票,买价格最低的即可

然后四票五票获取胜利的方法同理,我们只要取花费价格最少的状态即可

#include<bits/stdc++.h>
using namespace std;
struct person{
    int p,c;
}per[3010];
int f[3010];
int g[3010];
bool cmp(person A,person B)
{
    return A.c<B.c;
}
int main()
{
    int n,m;
    scanf("%d%d",&n,&m);
    for(int i=1;i<=n;i++)
    {
        scanf("%d%d",&per[i].p,&per[i].c);
        f[per[i].p]++;
    }
    long long res=3e12;
    sort(per+1,per+n+1,cmp);
    for(int i=f[1];i<=n;i++)
    {
        int sum=0;
        for(int j=2;j<=m;j++)
        {
            if(f[j]>=i)
            {
                g[j]=f[j]-i+1;
                sum+=g[j];
            }
            else g[j]=0;//此处不可省略, g数组要反复更新
        }
        if(i-f[1]<sum) continue;
        long long ans=0;
        sum=i-f[1]-sum;
        for(int j=1;j<=n;j++)
        {
            if(g[per[j].p]>0)
            {
                g[per[j].p]--;
                ans+=per[j].c;
            }
            else if(sum>0&&per[j].p!=1)
            {
                sum--;
                ans+=per[j].c;
            }
        }
        res=min(ans,res);
    }
    printf("%lld\n",res);
}

原文地址:https://www.cnblogs.com/lishengkangshidatiancai/p/10264066.html

时间: 2024-11-05 15:53:39

cf 1020 round 503(SIS div2) C. Elections的相关文章

Codeforces Round #503(div2) 做题记录

前几天有点咕,马上题解会跟上~ A. 题意: 有n个楼,每个楼有h层,相邻两个楼在(a,b)之间有通道 k次询问,每次问(tA,fA)到(tB,fB)(t为楼的编号,f为楼层)的最短路 题解: 如果不在(a,b)层之间那先爬到离他最近的(a,b)层之间的楼层 然后通过通道直接走,先走到tB走到对应楼层 注意tA=tB时特判 1 #include<bits/stdc++.h> 2 #define ll long long 3 using namespace std; 4 int n,h,a,b,

Codeforces Round #503 (by SIS, Div. 2)

Codeforces Round #503 (by SIS, Div. 2) https://codeforces.com/contest/1020 A 1 #include <iostream> 2 #include <cstring> 3 #include <cmath> 4 #include <algorithm> 5 #include <cstdio> 6 #include <cstdlib> 7 #include <s

Codeforces Round #FF(255) DIV2 C - DZY Loves Sequences

A - DZY Loves Hash 水题,开辟一个数组即可 #include <iostream> #include <vector> #include <algorithm> #include <string> using namespace std; int main(){ int p,n; cin >> p >> n; vector<bool> buckets(302,false); bool flag = fal

CF Edu Round 71

CF Edu Round 71 A There Are Two Types Of Burgers 贪心随便模拟一下 #include<iostream> #include<algorithm> #include<cstring> #include<cstdio> using namespace std; #define MAXN 200006 int n , m; int A[MAXN]; int b , p , f , h , c; int main()

Codeforces Round #503 (by SIS, Div. 2) C. Elections

气死我了人生中第一次打cf就掉分了 A题大水题浪费太多时间囧明明都是A两题亮老师还上分了.. 表示C题打的时候就想到正解啊(而且还更加优秀,因为家里老爷机暴力跑的超龟以为不行 其实是没认真算复杂度),虽然不会证三分性,但是最后还是AC了,暴力1000ms+ 三分40ms+ 看着就很奇淫的题,猛然脑海里就想到二分政党的最后得到的选票,然后发现没有单调性,但好像满足三分 然后每次就贪心,for一遍把那些比1政党本来就有的选票+要多拿的选票还要多的拿到比这个值少1 假如还不够要多拿的,那就在剩下的拿最

Codeforces Round #503 (by SIS, Div. 2) Partial Solution

从这里开始 题目列表 瞎扯 Problem A New Building for SIS Problem B Badge Problem C Elections Problem D The hat Problem E Sergey's problem 瞎扯 例行快速切A.B.C. 然后发现D是交互.E也不像是我能做的题,感觉完蛋了. 最后8分钟想出D.狂码代码,然后比赛结束后1分钟过样例. 第二天早上再花4分钟AC.我真是个大菜逼.. 于是这场cf比赛变成了真·手速场.几个friends手速比我

【CF】Round #618 div2 C(文末有技巧)

目录 round #618 div2 C(文末有技巧) 题目: 样例输入输出 思路 小技巧(拿小本本记下来) round #618 div2 C(文末有技巧) 这是题目链接->链接 题目: 原题目是全英文的,所以我就粗略来翻译一下: 有这样一个函数f:f(x,y)=(x|y)-y;(其中|是按位或操作) 比如说:f(11,6)=(11|6)-6=15-6=9;(简单明了) 现在有一个数组 [a1,a2,-,an],让你求f(f(-f(f(a1,a2),a3),-an?1),an) ,数组中可能有

在青岛穷游打的cf codeforces Round #318 (Div. 2) A.Bear and Elections

这场cf是暑假集训后在青岛旅游打的一场,好累..... 题意:给出一个序列,要使a[1]大于a[2]~a[n],a[1]每次可以增加一,这个一从a[2]到a[[n]里面任意一个数减一扣除,求最少的步数 思路:要不断地修改值,并从中找出最大的,可以想到优先队列,还要保存下该数的编号,要知道在队首时是a[1].还有处里一种特殊情况,详见代码 总结:这道题并不难,我用了40多分钟,主要前面太急了,一开始并没有想到是优先队列,是一些其他的想法,只要合适一个样例就下手去做,导致有很明显的bug我竟然敲完代

Codeforces Round #503 (by SIS, Div. 2) D. The hat -交互题,二分

cf1020D 题意: 交互题目,在有限的询问中找到一个x,使得数列中的第x位和第(x+n/2)位的值大小相同.数列保证相邻的两个差值为1或-1: 思路: 构造函数f(x) = a[x] - a[x + n/2] ,由于a数列差值为1或-1,所以可以发现f(x)是连续的.然后就可以用二分了,这种二分的check方式是自己第一次见的.就是通过f(mid)和f(d)的正负来判断区间的移动.其中d是任选的. 代码: #include <iostream> #include <cstdio>