机房测试3:C++锦标赛(贪心)

题目:

分析:

首先理解题意:zyg要和每一个人都打比赛,且只有输和赢两种情况,也就是说没打赢的人最后得分要++。

我们希望zyg打赢的人尽量地少,且rp值小。

先对比分大小排序,估计一下对应排名的最小分数sc,再按rp从小到大排序,然后分情况贪心:

1.使其最终得分为sc+2

只需要打赢前sc+2个人即可,没有其他人会影响到他。

2.最终得分为sc+1

我们担心得分为sc的人因为没有被打赢,得分+1而排在zyg前面,所以应该先处理得分为sc的人,把他们都打赢。

(同时也要打赢sc+1的人,否则按照题目要求也会在前面)

3.最终得分为sc

思路和上面一样:先打赢sc-1的人,再打赢sc,最后为了得到sc的分,从大到小加一遍。

#include<bits/stdc++.h>
using namespace std;
#define ri register int
#define N 2505
#define ll long long
struct node{ int p; ll e; }e[N];
int read()
{
    int x=0,fl=1; char ch=getchar();
    while(ch<‘0‘||ch>‘9‘) { if(ch==‘-‘) fl=-1; ch=getchar(); }
    while(ch>=‘0‘&&ch<=‘9‘) x=x*10+ch-‘0‘,ch=getchar();
    return x*fl;
}
int T,n,k,sc,vis[N],sl;
bool cmp1(const node &a,const node &b) { return a.p>b.p; }
bool cmp2(const node &a,const node &b) { return a.e<b.e; }
ll work1()
{
    ll tmp=0;
    for(ri i=1;i<=n&&i<=sc+2;++i) tmp+=e[i].e;
    return tmp;
}
ll work2()
{
    ll tmp=0; int g=sc+1,tsl=sl;
    for(ri i=0;i<=n;++i) vis[i]=0;
    for(ri i=1;i<=n&&tsl;++i)
    if(e[i].p==sc+1 || e[i].p==sc) g--,tsl--,tmp+=e[i].e,vis[i]=true;
    for(ri i=1;i<=n&&g>0;++i) if(!vis[i]) g--,tmp+=e[i].e;
    return tmp;
}
ll work3()
{
    ll tmp=0; int g=sc,tsl=sl,t2l=0;
    for(ri i=1;i<=n;++i){
        vis[i]=0;
        if(e[i].p==sc-1) t2l++;
    }
    for(ri i=1;i<=n&&tsl;++i)
    if(e[i].p==sc) tsl--,g--,vis[i]=true,tmp+=e[i].e;
    for(ri i=1;i<=n&&t2l;++i)
    if(!vis[i] && (e[i].p==sc-1 ||e[i].p==sc)) t2l--,g--,vis[i]=true,tmp+=e[i].e;
    for(ri i=1;i<=n&&g;++i)
    if(!vis[i]) g--,tmp+=e[i].e;
    return tmp;
}
bool check()
{
    int cnt=0;
    for(ri i=1;i<=n;++i) if(e[i].p>n) cnt++;
    if(cnt>k-1) return true;
    return false;
}
int main()
{
    freopen("tournament.in","r",stdin);
    freopen("tournament.out","w",stdout);
    T=read();
    while(T--){
        n=read(); k=read();
        for(ri i=1;i<=n;++i) e[i].p=read(),e[i].e=read();
        if(k==n+1) { printf("0\n"); continue; }
        if(check()) { printf("-1\n"); continue; }
        sort(e+1,e+1+n,cmp1);
        sc=e[k].p; sl=1;
        while(e[k+sl].p==e[k].p) sl++;
        sort(e+1,e+1+n,cmp2);
        ll ans=min(work1(),min(work2(),work3()));
        printf("%lld\n",ans);
    }
}
/*
1
4 5
1 77
3 26
3 69
1 28
*/

原文地址:https://www.cnblogs.com/mowanying/p/11623466.html

时间: 2024-11-02 01:28:53

机房测试3:C++锦标赛(贪心)的相关文章

机房测试:lunch(贪心+最短路)

题目: 分析: 由数据3得:既然所有人都要学会,肯定是越早学越优.(贪心重要思路) 所以转移就是:dis[v]=max( dis[u] ,L ),u学会之后传授给v的条件是:u先学会,传授的时间在吃饭的时间内 在最短路上转移即可 再考虑有人必须学不会的限制. 如果有一个人u没有学会,就会给他周围的人v一个限制:v不能太早学会,否则吃饭的时候v就会传授给u 所以将lim[v]定为L+1,即他们在L的时候吃饭,L+1的时候v才学会,不会传给u 先将这种传递关系用spfa预处理 再跑一边dij求出每个

机房测试1:big(贪心+Trie树)

题目: 分析: 考虑最暴力的办法:枚举选哪个数,枚举对手在哪个时间变化,然后统计答案. 对于异或这一类问题,考虑区间异或可以抵消重复区间,维护一个前缀异或和:pre[i]表示1~i的异或和,suf[i]表示i~n的异或和. 将对手的式子化简,2*x即将x向左移一位,/( 2^n )为向右移n位,+2*x ,%2^n类似. 模拟一下:12345 -> 123450 -> 123451 -> 23451 每次枚举对手要变的时间i,最后的值即为:work ( pre[i] ^ x ) ^ su

[20191004机房测试] C++锦标赛

有一个比赛已经有 n 个人参加,并且互相之间已经进行了比赛 每一个人都有一个得分用于最后排名 你作为第 n + 1 个参赛者,需要与之前的每一个人打一场比赛,初始得分为 0 对于每场比赛,有两个人参加,不会存在平局,胜者得分增加 1,败者得分不变 最后按照得分从高到低来排名,假设有人与你最终得分相同 那么如果那个人曾经输给了你就会排在你后面,否则会排在你的前面 如果你赢了某个人,就需要消耗相应的 RP 值 现在你可以决定赢那些人,求最少需要消耗多少 RP 值才能到前k名 50分做法:还是枚举二进

机房测试2:sushi(断环+贪心)

题目: 分析: 因为原序列是一个环,所以要断环为链,将序列复制一份放在后面. 显然将R移动到一块的同时,B也会在一块,所以只需要求R移动到一起的贡献即可. 枚举一个分界点,让这个点左边所有的R都向左靠,右边所有的R都向右靠.这时候一定是满足题意的. 但会发现,同一个分界点,随着断环的位置改变,统计出来的答案也会改变,所以还要枚举一个断环点. 复杂度是n^2 考虑优化: RRBBRBBBR 像这样一组数据,把将R向两边放看做是将B往中间靠,那么在第5个位置是最优的(左边移两格,右边不需要移). 当

Host1Plus主机商8个机房测试IP体验

Host1Plus商家也算是比较老的海外主机商(英国),当初进入中国市场也是比较早的,记得那时候支持支付宝的海外主机商尤其的深受用户喜欢.因为我 们大部分网友.站长最多有一个支付宝,很少有双币信用卡或者贝宝支付美元的能力.不过后来几年,HOST1PLUS商家逐渐的落寞,主要原因在于其他商家 的出现,以及他们本身营销能力和产品的策略. 尤其是提供的虚拟主机和VPS主机,价格和方案不是太符合中国用户的口味,配置比较低,而且机房较 少.不过商家应该意识到这一点,在最近2年改动挺大的,今天公司业务正好有

[CSP-S模拟测试]:C(三分+贪心)

题目传送门(内部题46) 输入格式 第一行$3$个整数$n,m,t$.第二行$n$个整数,表示$P_i$.接下来$m$行每行两个整数,表示$L_i,R_i$. 输出格式 一行一个整数表示答案. 样例 样例输入: 3 3 26 2 51 12 23 3 样例输出: 11 数据范围与提示 样例解释: 最优方案为使用$2$次特殊加热器,$4$次$1$号加热器,$3$次$3$号加热器. 数据范围: 对于前$20\%$的数据:$t\geqslant n$对于另$30\%$的数据:$P_i\leqslant

[CSP-S模拟测试]:Emotional Flutter(贪心)

题目传送门(内部题51) 输入格式 第一行一个整数$t$表示数据组数.每组数据的第一行有三个整数$s,k,n$.第二行有$n$个整数$A_1,A_2,...,A_n$,依次表示黑白条的长度. 输出格式 若能通过输出$"TAK"$,否则输出$"NIE"$. 样例 样例输入: 22 8 72 5 6 3 2 1 22 8 41 6 7 4 样例输出: TAKNIE 数据范围与提示 样例解释: 数据范围: $30\%$的数据,$n\leqslant 1300$: $50\

[20191004机房测试] ZGY的早餐

ZGY 每天早上要从宿舍走路到机房,顺便从学校小卖部购买早饭,当然机智的 ZGY 一定会走最短路 学校的路可以看成一无向联通张图,图上有 n 个点,m 条边,每一个点都有一个唯一的编号 1~n 每一条边有一个边权,表示两个点之间的距离,ZGY 的宿舍在 S 点,机房在 T点,而小卖部在 H 点 现在 ZGY 想知道从宿舍经过小卖部到达机房的最短距离 不过因为在这个世界上有 Q个 ZGY,所以你必须回答 Q 个问题 很棒的数据分治题 读入里面说了会读入测试点编号-- 其实是很明显的暗示了-- 一半

[CSP-S模拟测试]:Graph(图论+贪心)

题目描述 给定一张$n$个点$m$条边的无向图,每条边连接两个顶点,保证无重边自环,不保证连通你想在这张图上进行若干次旅游,每次旅游可以任选一个点$x$作为起点,再走到一个与 $x$直接有边相连的点$y$,再走到一个与$y$直接有边相连的点$z$并结束本次旅游 作为一个旅游爱好者,你不希望经过任意一条边超过一次,注意一条边不能即正向走一次又反向走一次,注意点可以经过多次,在满足此条件下,你希望进行尽可能多次的旅游,请计算出最多能进行的旅游次数并输出任意一种方案 输入格式 第$1$行两个正整数$n