题目大意
给出一个长度为n的数组a,每个位置可以为负。m次询问,对于a数组从左往右,循环累加,要加多少次才能让总值不小于b[i]
题目思路
为了方便计算我们需要一个关于a数组前缀的单调数组。
因为a数组中可能存在负数,所以他的前缀和不一定单调。
我们假设第i个数是负数,第i-1个数是正数,那么我们对于前i个数,我们一定是从1选到i-1优于1选到i。
那么对于每个i我们统计从1到i里面的前缀和最大值。
之后就是分类讨论。
当数组最大的前缀值大于等于b[i],那么说明循环一次就能找到答案,我们直接用二分函数求答案就好了。
当数组最大的前缀值小于b[i],那么说明需要进行多次循环来找到答案,然后模拟就好。
ac代码
const int maxn = 3e5+10;
const int inf = 1e9+10;
const ll llinf =1e18+10;
const ll mod = 1e9+7;
const double pi = acos(-1);
int n,m;
ll a[maxn],b[maxn];
ll dp[maxn];
int main()
{
int _;
scanf("%d",&_);
while(_--)
{
scanf("%d%d",&n,&m);
ll maxx=0;
for(int i=1;i<=n;i++)
{
scanf("%lld",&a[i]);
a[i]=a[i-1]+a[i];
dp[i]=max(dp[i-1],a[i]);
}
for(int i=1;i<=m;i++)
{
scanf("%lld",&b[i]);
if(dp[n]>=b[i])
{
int pos=lower_bound(dp+1,dp+1+n,b[i])-dp;
printf("%d ",pos-1);
}else
{
if(a[n]<=0)//总值不为正,无法构成答案,输出-1
{
printf("-1 ");
continue;
}
ll d=b[i]-dp[n];
ll ans=lower_bound(dp+1,dp+1+n,b[i]-a[n]*(ll)ceil(d*1.0/a[n]))-dp-1+(ll)ceil(d*1.0/a[n])*n;
printf("%lld ",ans);
}
}
pl;
}
}