Codeforces Round #702 (Div. 3)
比赛链接
Codeforces Round #702 (Div. 3)
给定序列 \(a\) ,把 \(a\) 反复制成一个无限序列,然后给 \(m\) 个询问,每次给定 \(x\) ,问 \(a\) 的第一个前缀和达到 \(x\) 的下标。
\(
a_{i}, x \leq 10^{9} \\
n, m \leq 2 * 10^{5}
\)
解题思路
二分
注意,本题要求的是达到而不是相等,不妨先求出一个循环中最大的前缀和 \(mx\),设前面进行了 \(t\) 轮循环,下一轮循环达到 \(x\),则有 \(mx+t\times s[n]\geq x\),则 \(t=\left \lceil \frac{x-mx}{s[n]} \right \rceil\),则在下一轮中找出满足条件的最小的下标即可。另外,需要特判第一轮的情况,然后如果第一轮结束后 \(s[n]\leq 0\),则肯定无法达到 \(x\)
这里有一个小技巧:求满足条件的最小下标时可以先求出前缀最值,再lower_bound
求解
- 时间复杂度:\(O(mlogn)\)
代码
// Problem: G. Old Floppy Drive
// Contest: Codeforces - Codeforces Round #702 (Div. 3)
// URL: https://codeforces.com/contest/1490/problem/G
// Memory Limit: 256 MB
// Time Limit: 2000 ms
//
// Powered by CP Editor (https://cpeditor.org)
// %%%Skyqwq
#include <bits/stdc++.h>
#define int long long
#define help {cin.tie(NULL); cout.tie(NULL);}
#define pb push_back
#define fi first
#define se second
#define mkp make_pair
using namespace std;
typedef long long LL;
typedef pair<int, int> PII;
typedef pair<LL, LL> PLL;
template <typename T> bool chkMax(T &x, T y) { return (y > x) ? x = y, 1 : 0; }
template <typename T> bool chkMin(T &x, T y) { return (y < x) ? x = y, 1 : 0; }
template <typename T> void inline read(T &x) {
int f = 1; x = 0; char s = getchar();
while (s < '0' || s > '9') { if (s == '-') f = -1; s = getchar(); }
while (s <= '9' && s >= '0') x = x * 10 + (s ^ 48), s = getchar();
x *= f;
}
const int N=2e5+5;
int t,n,m,a[N],s[N];
signed main()
{
for(cin>>t;t;t--)
{
cin>>n>>m;
s[0]=0;
for(int i=1;i<=n;i++)
{
cin>>a[i];
s[i]=s[i-1]+a[i];
}
int sum=s[n];
for(int i=2;i<=n;i++)s[i]=max(s[i],s[i-1]);
int mx=s[n];
while(m--)
{
int x;
cin>>x;
if(mx>=x)
{
cout<<lower_bound(s+1,s+1+n,x)-s-1<<' ';
continue;
}
if(sum<=0)cout<<-1<<' ';
else
{
int t=(x-mx+sum-1)/sum;
int res=t*n-1;
x-=t*sum;
int pos=lower_bound(s+1,s+1+n,x)-s;
res+=pos;
cout<<res<<' ';
}
}
puts("");
}
return 0;
}