题意:有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
*/