The standard solution to this problem uses a monotonic deque and runs in
Unable to parse markup [type=CF_MATHJAX]
$.
This post describes a different approach running in
Unable to parse markup [type=CF_MATHJAX]
$. Instead of maintaining a deque, we store the useful prefix sums in a monotonic vector and binary-search over it.
The whole idea comes from two simple observations:
- A smaller prefix sum is always better.
- If two prefix sums are equally good, the later index is always better.
Prefix Sum Formulation
Let
Unable to parse markup [type=CF_MATHJAX]
$ P_0=0,\qquad P_i=a_1+a_2+\cdots+a_i.
Unable to parse markup [type=CF_MATHJAX]
$
Then the sum of the subarray
Unable to parse markup [type=CF_MATHJAX]
$ equals
Unable to parse markup [type=CF_MATHJAX]
$ P_i-P_j.
Unable to parse markup [type=CF_MATHJAX]
$
We want
Unable to parse markup [type=CF_MATHJAX]
$ P_i-P_j\ge K,
Unable to parse markup [type=CF_MATHJAX]
$
or equivalently,
Unable to parse markup [type=CF_MATHJAX]
$ P_j\le P_i-K.
Unable to parse markup [type=CF_MATHJAX]
$
Therefore, for every right endpoint
Unable to parse markup [type=CF_MATHJAX]
$, we need the largest index
Unable to parse markup [type=CF_MATHJAX]
$ satisfying
Unable to parse markup [type=CF_MATHJAX]
$ P_j\le P_i-K.
Unable to parse markup [type=CF_MATHJAX]
$
Choosing the largest valid
Unable to parse markup [type=CF_MATHJAX]
$ minimizes the subarray length
Unable to parse markup [type=CF_MATHJAX]
$.
Removing Dominated Prefix Sums
Suppose
Unable to parse markup [type=CF_MATHJAX]
$ x<y
Unable to parse markup [type=CF_MATHJAX]
$
and
Unable to parse markup [type=CF_MATHJAX]
$ P_y\le P_x.
Unable to parse markup [type=CF_MATHJAX]
$
Then the prefix
Unable to parse markup [type=CF_MATHJAX]
$ is never useful again.
Indeed, if some future endpoint
Unable to parse markup [type=CF_MATHJAX]
$ satisfies
Unable to parse markup [type=CF_MATHJAX]
$ P_i-P_x\ge K,
Unable to parse markup [type=CF_MATHJAX]
$
then
Unable to parse markup [type=CF_MATHJAX]
$ P_i-P_y \ge P_i-P_x \ge K,
Unable to parse markup [type=CF_MATHJAX]
$
because
Unable to parse markup [type=CF_MATHJAX]
$.
Moreover,
Unable to parse markup [type=CF_MATHJAX]
$ i-y<i-x,
Unable to parse markup [type=CF_MATHJAX]
$
so using
Unable to parse markup [type=CF_MATHJAX]
$ always produces a shorter subarray.
Hence, whenever a new prefix sum arrives, every previous prefix sum that is greater than or equal to it can be removed permanently.
[code=cpp] while (!a.empty() && a.back().first >= p[i]) { a.pop_back(); } a.push_back({p[i], i}); [/code]
After every insertion, the stored pairs satisfy
Unable to parse markup [type=CF_MATHJAX]
$ P_{j_1}<P_{j_2}<\cdots<P_{j_m},
Unable to parse markup [type=CF_MATHJAX]
$
and their indices also satisfy
Unable to parse markup [type=CF_MATHJAX]
$ j_1<j_2<\cdots<j_m.
Unable to parse markup [type=CF_MATHJAX]
$
Thus the vector is strictly increasing in both coordinates.
Binary Search
For the current endpoint
Unable to parse markup [type=CF_MATHJAX]
$, define
Unable to parse markup [type=CF_MATHJAX]
$ T=P_i-K.
Unable to parse markup [type=CF_MATHJAX]
$
We need the last stored pair whose prefix sum is at most
Unable to parse markup [type=CF_MATHJAX]
$.
Since prefix sums are strictly increasing, every valid pair forms a prefix of the vector.
Since indices are also strictly increasing, the last valid pair has the largest possible index, exactly the one we want.
Therefore we simply do
[code=cpp] int pos = upper_bound( a.begin(), a.end(), make_pair(p[i] — k, i) ) — a.begin() — 1; [/code]
Searching for the pair
Unable to parse markup [type=CF_MATHJAX]
$ ensures that every stored prefix sum satisfying
Unable to parse markup [type=CF_MATHJAX]
$ is included.
Why Does This Work?
Lemma 1
If
Unable to parse markup [type=CF_MATHJAX]
$ and
Unable to parse markup [type=CF_MATHJAX]
$, then
Unable to parse markup [type=CF_MATHJAX]
$ can be removed forever.
Proof.
Whenever
Unable to parse markup [type=CF_MATHJAX]
$ forms a valid subarray with some future endpoint,
Unable to parse markup [type=CF_MATHJAX]
$ also forms a valid one because its prefix sum is no larger. Since
Unable to parse markup [type=CF_MATHJAX]
$, it always produces a shorter subarray. Hence
Unable to parse markup [type=CF_MATHJAX]
$ is never optimal again. ▢
Lemma 2
The maintained vector is strictly increasing in both prefix sums and indices.
Proof.
Indices are inserted from left to right. Before inserting a new prefix sum, all larger (or equal) suffix prefix sums are removed. Therefore both coordinates remain strictly increasing. ▢
Theorem
For every endpoint
Unable to parse markup [type=CF_MATHJAX]
$, the binary search returns the shortest valid subarray ending at
Unable to parse markup [type=CF_MATHJAX]
$.
Proof.
All feasible prefix sums form a prefix of the vector. Binary search returns the last element of this prefix, which has the largest valid index.
By Lemma 1, every removed prefix is dominated by another one, so deleting it never removes an optimal answer.
Taking the minimum over all endpoints therefore gives the globally shortest valid subarray. ▢
Implementation
[code=cpp] for (int i = 0; i <= n; i++) {
while (!a.empty() && a.back().first >= p[i]) {
a.pop_back();
}
a.push_back({p[i], i});
if (i == 0) continue;
int pos = upper_bound(
a.begin(),
a.end(),
make_pair(p[i] - k, i)
) - a.begin() - 1;
if (pos == -1) continue;
ans = min(ans, i - a[pos].second);
} [/code]
Here:
pis the prefix sum array.astores the non-dominated pairs
Unable to parse markup [type=CF_MATHJAX]
$.
For the original problem,
Unable to parse markup [type=CF_MATHJAX]
$, so inserting
Unable to parse markup [type=CF_MATHJAX]
$ before querying cannot create a zero-length answer because
Unable to parse markup [type=CF_MATHJAX]
$ P_i\not\le P_i-K.
Unable to parse markup [type=CF_MATHJAX]
$
Complexity
Each prefix sum is
- inserted once,
- removed at most once.
Thus all stack operations together take
Unable to parse markup [type=CF_MATHJAX]
$.
We perform one binary search for every prefix, so the total complexity is
Unable to parse markup [type=CF_MATHJAX]
$ O(n\log n).
Unable to parse markup [type=CF_MATHJAX]
$
Memory complexity is
Unable to parse markup [type=CF_MATHJAX]
$ O(n).
Unable to parse markup [type=CF_MATHJAX]
$
Final Perspective
The key object is not really a stack or a deque—it is the set of non-dominated prefix states.
A state
Unable to parse markup [type=CF_MATHJAX]
$ is dominated by
Unable to parse markup [type=CF_MATHJAX]
$ whenever
Unable to parse markup [type=CF_MATHJAX]
$ P_y\le P_x \quad\text{and}\quad y>x.
Unable to parse markup [type=CF_MATHJAX]
$
The second state is simultaneously
- easier to satisfy (smaller prefix sum),
- better for minimizing the answer (later index).
Maintaining only these non-dominated states creates a monotone frontier that is increasing in both prefix sum and index. The monotonic deque solution exploits the same dominance relation to achieve
Unable to parse markup [type=CF_MATHJAX]
$, while this approach replaces deque queries with binary search, yielding a simpler
Unable to parse markup [type=CF_MATHJAX]
$ alternative.



