结构体lower_bound
思路很简单,之前在牛客写过一道类似的题目,那道题的题面是勇者屠恶龙打BOSS,可以除一下然后直接暴力,这道不行,要用二分查找,1900标高了。
记录一下a数组总和sum和最大值Max,可以算出答案所在轮次,然后再二分查找具体的下标,有一个细节就是可以在记录Max的时候把每次更新Max的值用结构体存起来,因为如果后面的值比当前更新的值小的话那就没有意义,后面直接二分这个结构体数组就可以。
#include<bits/stdc++.h>
#define LL long long
#define INF INT64_MAX
#define MOD 1000000007
#define stree SegTree[root]
#define lson SegTree[root << 1]
#define rson SegTree[root << 1 | 1]
using namespace std;
const int N = 200005;
LL a[N];
struct node
{
LL val, pos;
bool operator < (const node &b) const
{
if(val!=b.val) return val<b.val;
else return pos>b.pos;
}
}b[N], tem;
int main()
{
int t, n, m, x;
cin>>t;
while(t--)
{
cin>>n>>m;
LL sum = 0, Max = -INF, cnt = 0;
for(int i = 1;i <= n;i++)
{
cin>>a[i];
sum += a[i];
if(sum>Max)
{
b[cnt].val = sum;
b[cnt++].pos = i;
}
Max = max(Max, sum);
}
while(m--)
{
cin>>x;
tem.pos = INF;
if(Max<x && sum<=0) printf("-1 ");
else
{
LL ans = 0;
tem.val = x;
if(x>Max)
{
ans = ((x-Max+sum-1)/sum)*n;
tem.val = x-((x-Max+sum-1)/sum)*sum;
}
int it = lower_bound(b, b+cnt, tem)-b;
printf("%lld ", ans-1+b[it].pos);
}
}
printf("\n");
}
return 0;
}