补题记录G. Old Floppy Drive

G. Old Floppy Drive

题意:给你一个长度为n的数组a,求出其中的前缀和数组s,然后有m次询问,每次询问给出一个数x,问使得a中前len个数的和刚好不小于x的个数-1是多少。如果一轮完成不了,就接着下轮继续加。
例如:原数组为[1,3,4]于是前缀和数组为[1,2,2],假如询问的是1,直接输出0即可(s[1]=1)假如询问的是5,则发现一轮完成不了,于是多组继续加。
1+(3)+4+1+(3)+4+1=5所以输出6
方法:二分
首先对于每次询问有多种情况,我们分类来想
设前缀和数组中的最大值为maxn,切s[n]为T(即一个周期,因为我们发现最终数组会呈现出[s1,s2,s3...sn,T+s1,T+s2,...T+s3,2T+s1,2T+s2...])
1、maxn<x&T0 容易得知这种情况下,是不可能到达目标的,所以直接输出-1
2、maxn<x&T>0
3、maxnx&T0
4、maxnx&T>0
其中的3,4为一类,我们先讲这个情况
对于这种情况,我们容易知道是不用进行第二轮的,第一轮内就能解决,于是就变成了在s数组中找到第一个大于等于x的数。我们用一个maxn数组来解决,maxs[i]表示前i个数中最大的数是多少,发现此时的max_s数组具有单调性,二分即可

int l = 1, r = n;
while (l < r) {
	int mid = (l + r) >> 1;
	if (max_s[mid] >= x) r = mid;
	else l = mid + 1;
}
cout << l - 1 << ' ';

其实第二类也差不多,我们发现如果要找一定要找周期最小的,那对于哪个数字来说可以用更小的周期到达数字呢?当然是最大的数了,所以我们最初先定下一个round,然后再用maxn数组进行二分验证即可

int round = (x - maxn + T - 1) / T;
int l = 1, r = n;
while (l < r) {
	int mid = (l + r) >> 1;
	if (round * T + max_s[mid] >= x) r = mid;
	else l = mid + 1;
}
cout << round * n + l - 1 << ' ';

加个预处理就行啦
友情提示:别忘了开long long

#include <bits/stdc++.h>
using namespace std;
typedef long long LL;
typedef pair<int, int> PII;
typedef pair<LL,LL> PLL;
const int INF = 0x3f3f3f3f, N = 2e5 + 10;
inline int lc(int u) {return u << 1;}
inline int rc(int u) {return u << 1 | 1;}
inline int lowbit(int x) {return x & (-x);}
LL max_s[N], s[N];
inline void solve() {
    int n, m; cin >> n >> m;
    LL maxn = -1e9;
    max_s[0] = -1e9;
    for (int i = 1; i <= n; i ++ ) {
        int x; cin >> x;
        s[i] = s[i - 1] + x;
        maxn = max(maxn, s[i]);
        max_s[i] = max(max_s[i - 1], s[i]);
    }
    LL T = s[n];
    while (m -- ) {
        int x; cin >> x;
        if (maxn < x && T <= 0) cout << -1 << ' ';
        else {
            if (maxn >= x) {
                int l = 1, r = n;
                while (l < r) {
                    int mid = (l + r) >> 1;
                    if (max_s[mid] >= x) r = mid;
                    else l = mid + 1;
                }
                cout << l - 1 << ' ';
            } else {
                LL round = (x - maxn + T - 1) / T;
                int l = 1, r = n;
                while (l < r) {
                    int mid = (l + r) >> 1;
                    if (round * T + max_s[mid] >= x) r = mid;
                    else l = mid + 1;
                }
                cout << round * n + l - 1 << ' ';
            }
        }
    }
    cout << '\n';
}
int main() {
    ios::sync_with_stdio(false), cin.tie(nullptr);
    int t; cin >> t;
    while (t -- )
        solve();
    return 0;
}
posted @   Time_Limit_Exceeded  阅读(55)  评论(0编辑  收藏  举报
编辑推荐:
· SQL Server 2025 AI相关能力初探
· Linux系列:如何用 C#调用 C方法造成内存泄露
· AI与.NET技术实操系列(二):开始使用ML.NET
· 记一次.NET内存居高不下排查解决与启示
· 探究高空视频全景AR技术的实现原理
阅读排行:
· 阿里最新开源QwQ-32B,效果媲美deepseek-r1满血版,部署成本又又又降低了!
· 单线程的Redis速度为什么快?
· SQL Server 2025 AI相关能力初探
· AI编程工具终极对决:字节Trae VS Cursor,谁才是开发者新宠?
· 展开说说关于C#中ORM框架的用法!

阅读目录(Content)

此页目录为空

点击右上角即可分享
微信分享提示