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;
}
标签:int,mid,702,Codeforces,单调,轮数,Div,lun
From: https://www.cnblogs.com/ycllz/p/16874581.html