1 条题解

  • 0
    @ 2087-3-15 2:40:21

    训练(training)

    解题思路

    所有a[i]非负,可用滑动窗口。右端right逐步扩张并加上a[right];只要窗口和≥S,就记录长度,再移走左端并让left前进,尽量缩短当前窗口。

    不断缩短到和<S后继续扩张。若整个过程从未达标,输出-1。

    正确性说明

    对固定右端,左端不断右移会使窗口和不增加,因此可以持续缩短到首次失效,其前一步就是该右端的最短合法窗口。所有右端均被检查;非负性也保证被移除的左端不会在未来产生更短而遗漏的答案。取所有合法窗口最小长度即全局最优。

    易错点

    0不破坏非负单调性;S达10^18,窗口和用long long;不能用严格>替代≥。

    复杂度

    时间O(n),空间O(n)。

    参考代码(C++11)

    #include <bits/stdc++.h>
    using namespace std;
    
    int main() {
        ios::sync_with_stdio(false);
        cin.tie(nullptr);
        int n;
        long long S;
        cin >> n >> S;
        vector<long long> a(n);
        for (auto &x : a)
            cin >> x;
        int left = 0, best = n + 1;
        long long sum = 0;
        for (int right = 0; right < n; right++) {
            sum += a[right];
            while (left <= right && sum >= S) {
                best = min(best, right - left + 1);
                sum -= a[left++];
            }
        }
        cout << (best == n + 1 ? -1 : best) << "\n";
        return 0;
    }
    
    • 1