题目链接:Problem - G2 - Codeforces
主要思路:记录到达每个点的最短位置,然后因为第一次出发只能从左边出发所以不确定在哪个点开始继续最短所以遍历从每个点出发。然后吧到达每个点的距离排序,用前缀和记录走过前面n个的体力然后二分找到是第几个位置。
#include<iostream>
#include<cmath>
#include<cstring>
#include<algorithm>
#include<map>
#include<queue>
#include<stack>
typedef long long ll;
using namespace std;
struct hh{
ll x,y;
};
int cmp(hh l,hh r){
return l.y<r.y;
}
hh a[200005];
ll c[200005];
void solve(){
ll n,sum=0;
cin>>n>>sum;
for(int i=1;i<=n;i++){
ll tmp;
cin>>tmp;
a[i].x=tmp+i;
a[i].y=min(tmp+i,tmp+n-i+1);
}
sort(a+1,a+n+1,cmp);
for(int i=1;i<=n;i++)
{
c[i]=c[i-1]+a[i].y;
}
ll ans=0;
for(int i=1;i<=n;i++){
if(a[i].x<=sum){
ll l=0,r=n,mid;
while(l<r)
{
mid=(l+1+r)/2;
ll val=c[mid];
if(mid>=i)
{
val-=a[i].y;
}
if(val+a[i].x<=sum)
{
l=mid;
}
else
{
r=mid-1;
}
}
ans=max(ans,l+(l<i));
}
}
cout<<ans<<endl;
}
int main(){
ll t;
cin>>t;
while(t--){
solve();
}
}