Codeforces Round #702 (Div. 3) G

G. Old Floppy Drive

维护一个前缀和
再维护一个单调的前缀和 因为我们后面的数花费更大 只有贡献更大的时候才会有用
这样就好做了 对于每个查询我们知道他最少的轮数肯定时单调的减去最后一个数/一轮的值上取整
但是前面会有数比他花费少一点 记住我们前面是具有单调性的 我们直接二分出这个数
然后直接计算答案即可
还有一种情况就是一轮的值lun是<=0的 这个时候我们直接对着这个单调的序列二分即可 不行就-1
最后注意这里x>=v.back()的时候我们才去二分这个最少的轮数对应最小的下标
不然我们这里轮数会变成负数 还会算出负数的轮数就可以得到
最后就是输出的时候都要-1

void solve(){
    int n,m;cin>>n>>m;
    vector<int>s(n+10);
    vector<int>v,pos;
    int lun=0;
    for(int i=1;i<=n;i++)cin>>s[i],lun+=s[i],s[i]+=s[i-1];
    for(int i=1;i<=n;i++){
        if(v.empty())v.push_back(s[i]),pos.push_back(i);
        else if(v.back()<s[i])v.push_back(s[i]),pos.push_back(i);
    }
    for(int i=1;i<=m;i++){
        int x;cin>>x;
        if(lun<=0){
            auto it=lower_bound(all(v),x);
            if(it==v.end())cout<<-1<<' ';
            else cout<<pos[it-v.begin()]-1<<' ';
            continue;
        }
        int l=0,r=(int)v.size()-1;
        int now=up(x-v.back(),lun);
        if(x>=v.back()) {
            while (l < r) {
                int mid = l + r >> 1;
                if (up(x - v[mid], lun) == now)r = mid;
                else l = mid + 1;
            }
            cout << up(x - v[l], lun) * n + pos[l] - 1 << ' ';
        }else{
            auto it=lower_bound(all(v),x);
            cout<<pos[it-v.begin()]-1<<' ';
        }
    }
    cout<<endl;
}
posted @ 2022-11-09 17:28  ycllz  阅读(20)  评论(0)    收藏  举报