题意:
数据范围:1<=n,m<=2e5,-1e9<=a(i)<=1e9,1<=x<=1e9
解法:
令sum[]为a[]的前缀和,
ma[]为sum[]的前缀max.
(首先,观察到询问的x一定是>=1的)
对于询问x,如果x已经被标记,那么可以直接返回答案.
1.如果sum[n]<=0,且x>ma[n],那么一定无解.
如果x<=ma[n],那么直接在ma[]上二分出一个最小的pos2,
满足ma[pos2]>=x即可.
2.如果sum[n]>0:
由于每一轮坐标一定是增大的,
二分出一个最小的pos,满足pos*sum[n]+ma[n]>=x,
然后再在ma[]上二分出一个最小的pos2,
满足ma[pos2]>=x-pos*sum[n]即可.
code:
#include <bits/stdc++.h>
#define int long long
using namespace std;
const int maxm=2e6+5;
int sum[maxm];
int ma[maxm];
int a[maxm];
int n,m;
int check(int mid,int x){
return 1.0*mid*sum[n]+ma[n]>=x;//这里爆longlong呀
}
int getpos(int x){
int l=0,r=1e9;
int pos=-1;
while(l<=r){
int mid=(l+r)/2;
if(check(mid,x))pos=mid,r=mid-1;
else l=mid+1;
}
return pos;
}
int cal(int x){
int pos=-1;
if(sum[n]<=0){
if(x>ma[n])return -1;
else pos=0;
}else{
pos=getpos(x);
}
int t=x-pos*sum[n];
int l=1,r=n;
int pos2=-1;
while(l<=r){
int mid=(l+r)/2;
if(ma[mid]>=t)pos2=mid,r=mid-1;
else l=mid+1;
}
return pos*n+pos2;
}
void solve(){
cin>>n>>m;
for(int i=1;i<=n;i++){
cin>>a[i];
}
ma[0]=-1e18;
sum[0]=0;
for(int i=1;i<=n;i++){
sum[i]=sum[i-1]+a[i];
ma[i]=max(ma[i-1],sum[i]);
}
while(m--){
int x;cin>>x;
int ans=cal(x);
if(ans!=-1)ans--;
cout<<ans<<' ';
}
cout<<endl;
}
signed main(){
ios::sync_with_stdio(0);
int T;cin>>T;
while(T--){
solve();
}
return 0;
}