CSES - Increasing Array Queries

Author: Andi Qu

Appears In

Time Complexity: O((N+Q)logN)\mathcal O((N + Q) \log N).

In this problem, we can answer the queries offline (i.e. read in the queries and process them in a different order). More specifically, we process queries in order of their left endpoints.

First, let's think about how we'd answer a single query (l,r)(l, r). Consider the following algorithm:

  • Let mx0=0\texttt{mx}_0 = 0 and j=0j = 0.
  • For each ii in [l,r][l, r]:
    • If xi>mxjx_i > \texttt{mx}_j, then set mxj+1=xi\texttt{mx}_{j + 1} = x_i and increment jj.
    • Otherwise, add mxjxi\texttt{mx}_j - x_i to the answer.

Notice how each mxj\texttt{mx}_j (except the last) contributes a fixed amount to the answer, regardless of rr. If pref\texttt{pref} is the prefix sum array of xx and idxj\texttt{idx}_j is the index of mxj\texttt{mx}_j in xx, then this amount is

(idxj+11idxj)mxj(prefidxj+11prefidxj)(\texttt{idx}_{j + 1} - 1 - \texttt{idx}_j) \cdot \texttt{mx}_j - (\texttt{pref}_{\texttt{idx}_{j + 1} - 1} - \texttt{pref}_{\texttt{idx}_j})

This means that for a fixed ll, we can compute each mxj\texttt{mx}_j and their contributions, and then use std::upper_bound and a BIT to answer queries with variable rr!

If we want to change ll, notice how we can update mx\texttt{mx} efficiently by using a monotone stack. Since each mxj\texttt{mx}_j's contribution depends on xix_i after it, the contributions of the old mxj\texttt{mx}_j don't change.

Again, we use std::upper_bound and a BIT to answer queries.

C++

#include <bits/stdc++.h>
typedef long long ll;
using namespace std;
const ll INF = 1e18;
int n, q;
ll x[200002], pref[200002], ans[200002];
ll contrib[200002], bit[200002];
vector<pair<int, int>> bckt[200001];

Join the USACO Forum!

Stuck on a problem, or don't understand a module? Join the USACO Forum and get help from other competitive programmers!