C. Yet Another Tournament

原题链接:Problem - C - Codeforces

题意:有n个人和你一起比赛,每个人有一个时间a[i]

对于n个人之间,比编号,i>j的话第i个人赢

你有总共m的时间,你和这n个人比,你只有花费的时间>=a[i]才能赢下标为i的人

换句话来说,如果m>=a[3]+a[6]+a[10]+a[x],那么你就可以赢3,6,10,x这四个人

名称按照赢的次数多来拍,比如有3个人赢5次,1个人赢1次,2个人赢0次

那么前三个人排第一,第四个人排第四,后两个人排第五

求你能排到的最小的名次

思路:如果我们要排前面的话就要赢的多,那么想赢的多我们就贪心的挑a小的人比

那么把a按从小到大取之后,算出来我们最多能赢x局

那么对于每个人i,最少赢i-1局最多赢i局

那么n个人至少赢的局数是:

0 1 2 3 ... x x+1 ...n-1

因为我们最多赢x局,所以我们不可能比至少赢x+1局的人(下标为x+2)的名次高,也不可能比至少赢x-1 的人(下标为x)的名次低,因为他最多赢x局。

那么我们就看能不能赢至少赢x局的人(下标为x+1),假设我们没有赢他,我们的名次是n-x+1,如果我们赢了他,他的局数就是x,我们的局数也是x,我们的名次就可以再提升一名(和他并列),那么我们就想办法看看能不能赢下标为x+1的人

有两种情况:

如果我们已经赢了x+1的人,我们就直接提升一名

如果我们没有赢x+1的人,那么我们就看能不能把在之前赢过的人里面挑一个人把他换成x+1,根据贪心我们肯定选赢过的a最大的人

假设我们m的时间在赢了x个人之后还剩下y,那么我们就看y加上赢过的最大的a能不能>=a[x+1],如果大于说明我们可以换,名次提升,如果不能就换不了。

#include<bits/stdc++.h>
using namespace std;
#define int long long
int n,m;
const int N=5e5+10;
int a[N],b[N];
void sove(){
    cin>>n>>m;
    int sum=0;
    for(int i=1;i<=n;i++){
        cin>>a[i];
        b[i]=a[i];
        sum+=a[i];
    }
    
    if(m>=sum){
        cout<<1<<endl;
        return ;
    }
    sort(b+1,b+1+n);
    int con=0,id=-1;
//    cout<<"sum=="<<sum<<endl;
    for(int i=1;i<=n;i++){
        if(m>=b[i]){
            m-=b[i];
            con++;
            id=i;
        }else{
            break;
        }
    }
    if(id==-1){
        cout<<n+1<<endl;
        return ;
    }
//    cout<<"con=="<<con<<endl;
    int ans=n-con+1;
    if(m+b[id]>=a[con+1]){
        ans--;
    }
    cout<<ans<<endl;
}
signed main(){
    int t;
    cin>>t;
    while(t--){
        sove();
    }
    return 0;
}
/*
1
5 0
1 1 1 1 1
*/

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 1
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值