Two families of “over all subarrays” problems. Both rest on the fact that the aggregate changes few times as the left end moves.
Few distinct values per right end
Fix the right end and move leftwards. Then changes times, because each change at least halves it. and change times, because each change sets or clears a bit. LCM changes times while it stays below a bound . (Min and max do not have this property; use a monotonic stack for those.)
Proof: gcd, OR, AND and (bounded) LCM change times as decreases
Let for fixed , as runs from down to . gcd: divides , so each step either keeps unchanged or strictly decreases it to a proper divisor, which is at most half of (a proper divisor of is at most , since the next smaller divisor-multiple is ). A strictly positive integer can halve at most times before reaching , so gcd changes value at most times. OR: (as a bitset), so the value only ever gains set bits or stays the same; since there are bits, it changes at most times. AND: symmetric, only loses set bits, same bound. LCM: is a multiple of , so each change at least doubles it (the next distinct multiple of that is itself a multiple structure is at least ), and it’s capped by , giving changes before exceeding the cap.
Keep the list of (value, number of left ends) runs for the current and extend it by :
// runs: (value of op(a[l..r]), count of l giving it), most recent first
template<class Op> map<ll, ll> countByValue(const vector<ll>& a, Op op) {
map<ll, ll> total;
vector<pair<ll, ll>> cur;
for (ll x : a) {
vector<pair<ll, ll>> nxt = {{x, 1}};
for (auto [v, c] : cur) {
ll w = op(v, x);
if (w == nxt.back().first) nxt.back().second += c; else nxt.push_back({w, c});
}
cur = move(nxt);
for (auto [v, c] : cur) total[v] += c;
}
return total;
}That’s operations (gcd costs another in theory, but each chain of gcds telescopes to total per position).
Uses:
- count subarrays with gcd (or OR, AND) equal to , for many queries ;
- number of distinct ORs over all subarrays;
- sum over all subarrays of gcd times length: store the leftmost of each run;
- shortest or longest subarray with gcd ending at ;
- “is there a subarray with gcd / OR ”, and minimum length;
- range queries “how many subarrays inside have gcd ”: sweep , and runs become range-add events on a BIT indexed by .
Two pointers with gcd: gcd isn’t invertible, so the window needs a two-stack queue or a sparse table. With a sparse table, is for a static array, since overlapping ranges are harmless for gcd.
Mex over subarrays
The mex of a set is the smallest non-negative integer not in it.
Mex of the whole array with updates: keep cnt[v] for and a segment tree (or a set of absent values) over that finds the first with cnt[v] == 0. Values larger than never matter, since the mex is at most .
Mex of a query range, offline: sweep and maintain last[v] = last position of in a segment tree over values storing the minimum of last. The mex of is the first with last[v] < l, found by descending. Make it persistent over to answer online. .
Proof: the min-of-last-occurrence tree finds the mex
At sweep position ,
last[v]is the most recent index where value occurs (or if never occurred up to ). A value lies in the range iff its most recent occurrence up to is , i.e. ifflast[v] >= l; so is absent from ifflast[v] < l. The mex of is by definition the smallest absent from it, i.e. the smallest withlast[v] < l— and since the segment tree stores the minimum oflastover each value-range, descending toward the side whose minimum is at every level finds exactly the smallest such (if the minimum over the whole range is , every value up to is present and the mex exceeds the tree’s domain, which the construction caps at since the mex of any range of length is at most ). Persisting one version of the tree per sweep position lets a later query re-run this same descent against the tree as it stood at that , answering online.
Which values are mexes of some subarray (CF 1436E): is the mex of some subarray iff some maximal segment avoiding (between consecutive occurrences of , or before the first or after the last) contains all of . Sweep with the same “min of last positions over ” tree, and check each gap when its closing occurrence of arrives. .
Proof: the CF 1436E criterion
() If a maximal -avoiding segment contains all of , then ‘s mex is exactly : every value is present (given) and itself is absent (the segment avoids by construction), so is the smallest absent value. () Conversely, if some subarray has mex exactly , then contains every value and no occurrence of — so lies entirely within one maximal -avoiding segment (the one containing it, since it has no inside), and that larger maximal segment, containing as a subset, also contains all of . So the criterion is exactly “some maximal -avoiding segment contains ”. Sweeping and checking each gap exactly when its closing occurrence of is reached (so the gap’s full extent is known) and the “min of last positions over ” tree is up to date for that extent, correctly evaluates the criterion online in total (summing over the values of with work each via the tree descent).
Counting and summing mex over all subarrays:
- Fix the left end and track = mex of , which is non-decreasing in . Compute for in one pass.
- Moving to deletes : for before the next occurrence of , the new value is . Since is monotone, that’s a range assign on a suffix of that interval, found by binary search on the segment tree. Summing after each step gives the sum of mexes over all subarrays in .
Proof: is non-decreasing, and the deletion update is correct
Monotonicity: as a multiset of distinct values present, so every value present in is still present in ; the mex (smallest absent value) can only increase or stay the same as the set of present values grows. Deletion update: removing when moving to can only affect for in the window before ‘s next occurrence (call it , where is that next occurrence) — for , still occurs again within , so its presence is unaffected and is unchanged. For , is now completely absent from where it used to be present (at position ). If the old mex , removing changes nothing ( wasn’t the thing determining the mex, since values below it were already the bottleneck or itself wasn’t yet “needed”). If , then means was one of the values that were all present; removing it makes now absent, so the new mex becomes exactly (every value below is still present, unaffected by removing , and itself is now the smallest absent value). Combining both cases: the new value is . Since is non-decreasing in , the set of with (where the update actually changes something, assigning them to ) is a contiguous suffix of the window , found by binary searching for the first with .
- Alternatively, . For a permutation each count is a rectangle determined by the span of the positions of , so the whole sum is .
Proof: , and the permutation rectangle count
The mex of a subarray is means it contains but not , so (summing the indicator for gives , and for the indicator is since itself, hence everything after, is missing or possibly more). Summing over all subarrays and swapping the order of summation gives . For a permutation of , each value has a unique position, so “containing all of ” means the subarray’s range satisfies and — a rectangle of valid pairs of size where are the min/max positions of , computable incrementally in per by maintaining a running min/max as increases, giving total.
Mex of a set as a game value: Grundy numbers are mexes; see Sprague-Grundy.
Mex with permutations: in a permutation of , the mex of a subarray is iff the subarray contains positions of and not the position of . Fixing gives a rectangle of valid , counted in , so all-subarray statistics on permutations are .