题意:
给出一个数组 a a a,最开始指针指向 a 1 a_1 a1,每过一秒指针就会向后移动一个,当到达 a n a_n an后又会回到 a 1 a_1 a1,每经过一个元素,就会得到这个元素的值,当得到的值总和 ≥ x \geq x ≥x时,就会停止,现在给出一些询问 x i x_i xi,问什么时候会停止。
题解:
一开始看题以为是等于x才停,想了好久,大意了。
先求出每个位置的前缀和 s u m [ i ] sum[i] sum[i],在对前缀和取前缀最大值,即 d p [ i ] = max j = 1 i s u m [ j ] dp[i]=\max\limits_{j=1}^{i} sum[j] dp[i]=j=1maxisum[j]。
如果 d p [ n ] ≥ x dp[n] \geq x dp[n]≥x,那么因为满足单调性,所以直接二分查找就行。
否则如果 s u m [ n ] ≤ 0 sum[n] \leq 0 sum[n]≤0,那么肯定没法到达x,直接输出-1。
当 s u m [ n ] > 0 sum[n]>0 sum[n]>0时, x − d p [ n ] x-dp[n] x−dp[n]就是至少还需要的值,那么可以求出至少要遍历完几次数组,
即 ( x − d p [ n ] ) / s u m [ n ] + ( ( x − d p [ n ] ) % s u m [ n ] > 0 ) (x-dp[n])/sum[n]+((x-dp[n]) \% sum[n]>0) (x−dp[n])/sum[n]+((x−dp[n])%sum[n]>0),最后再对剩下的数进行二分即可。
代码
#include<cstdio>
#include<iostream>
#include<algorithm>
#include<cstring>
#include<cmath>
#include<queue>
#include<map>
#include<stack>
#include<set>
#include<ctime>
#define iss ios::sync_with_stdio(false)
using namespace std;
typedef unsigned long long ull;
typedef long long ll;
typedef pair<int,int>pii;
const int MAXN=2e5+5;
const int mod=1e9+7;
const int inf=0x3f3f3f3f;
ll dp[MAXN];
ll a[MAXN];
int main()
{
int t;
cin>>t;
while(t--)
{
int n,m;
cin>>n>>m;
ll sum=0;
dp[0]=-1e18;
for(int i=1;i<=n;i++)
{
cin>>a[i];
sum+=a[i];
dp[i]=max(sum,dp[i-1]);
}
while(m--)
{
ll x;
cin>>x;
if(dp[n]>=x)
{
int ans=lower_bound(dp+1,dp+1+n,x)-dp;
printf("%d ",ans-1);
continue;
}
if(sum<=0)
{
printf("-1 ");
continue;
}
ll d=x-dp[n];
ll p=(d+sum-1)/sum;
x-=p*sum;
ll ans=lower_bound(dp+1,dp+1+n,x)-dp+p*n-1;
printf("%lld ",ans);
}
cout<<endl;
}
}