Codeforces Round #702 (Div. 3) G. Old Floppy Drive

题目大意

给出一个长度为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;
    }
}
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值