Use this to learn the idea, then write your own version.
123 45class Solution {6private:7 struct TupleHash {8 template <typename... T>9 std::size_t operator()(const std::tuple<T...>& t) const {10 return apply([](const auto&... args) {11 std::size_t seed = 0;12 ((seed ^= std::hash<std::decay_t<decltype(args)>>{}(args) + 13 0x9e3779b9 + (seed << 6) + (seed >> 2)), ...);14 return seed;15 }, t);16 }17 };18 19public:20 long long maxTotalValue(vector<int>& nums, int k) {21 vector<int> idxs(size(nums));22 iota(begin(idxs), end(idxs), 0);23 sort(begin(idxs), end(idxs), [&](const auto& a, const auto& b) {24 return nums[a] != nums[b] ? nums[a] < nums[b] : a < b;25 });26 const auto& nxt = [&](int left, int right, int i, int j) {27 for (; !(left <= idxs[i] && idxs[i] <= right); ++i);28 for (; !(left <= idxs[j] && idxs[j] <= right); --j);29 return tuple(i, j);30 };31 32 unordered_map<tuple<int, int>, tuple<int, int>, TupleHash> lookup;33 lookup[{0, size(idxs) - 1}] = {0, size(idxs) - 1};34 using P = pair<int, pair<int, int>>;35 priority_queue<P> max_heap;36 max_heap.push({nums[idxs[size(idxs) - 1]] - nums[idxs[0]], {0, size(idxs) - 1}});37 int64_t result = 0;38 while (k) {39 const auto [v, l_r] = max_heap.top(); max_heap.pop();40 const auto& [l, r] = l_r;41 const auto& [i, j] = lookup[{l, r}];42 const auto& nl = min(idxs[i], idxs[j]);43 const auto& nr = max(idxs[i], idxs[j]);44 const int64_t c = min((nl - l + 1) * (r - nr + 1), k);45 k -= c;46 result += c * v;47 if (nl + 1 <= r && !lookup.count({nl + 1, r})) {48 const auto& [ni, nj] = nxt(nl + 1, r, i, j);49 lookup[{nl + 1, r}] = {ni, nj};50 max_heap.push({nums[idxs[nj]] - nums[idxs[ni]], {nl + 1, r}});51 }52 if (l <= nr - 1 && !lookup.count({l, nr - 1})) {53 const auto& [ni, nj] = nxt(l, nr - 1, i, j);54 lookup[{l, nr - 1}] = {ni, nj};55 max_heap.push({nums[idxs[nj]] - nums[idxs[ni]], {l, nr - 1}});56 }57 }58 return result;59 }60};61 62636465class Solution2 {66public:67 long long maxTotalValue(vector<int>& nums, int k) {68 SparseTable rmq_min(nums, [](const auto& a, const auto& b) {69 return a < b ? a : b;70 });71 SparseTable rmq_max(nums, [](const auto& a, const auto& b) {72 return a > b ? a : b;73 });74 using P = pair<int, pair<int, int>>;75 vector<P> arr(size(nums));76 for (int i = 0; i < size(nums); ++i) {77 arr[i] = {rmq_max.query(i, size(nums) - 1) - rmq_min.query(i, size(nums) - 1), {i, size(nums) - 1}};78 }79 priority_queue<P> max_heap(cbegin(arr), cend(arr));80 int64_t result = 0;81 for (int _ = 0; _ < k; ++_) {82 const auto [v, i_j] = max_heap.top(); max_heap.pop();83 const auto& [i, j] = i_j;84 result += v;85 if (i <= j - 1) {86 max_heap.push({rmq_max.query(i, j - 1) - rmq_min.query(i, j - 1), {i, j - 1}});87 }88 }89 return result;90 }91 92private:93 94 class SparseTable {95 public:96 SparseTable(const vector<int>& arr, function<int (int, int)> fn)97 : fn(fn) { 98 const int n = size(arr);99 const int k = __lg(n);100 st.assign(k + 1, vector<int64_t>(n));101 st[0].assign(cbegin(arr), cend(arr));102 for (int i = 1; i <= k; ++i) {103 for (int j = 0; j + (1 << i) <= n; ++j) {104 st[i][j] = fn(st[i - 1][j], st[i - 1][j + (1 << (i - 1))]);105 }106 }107 }108 109 int64_t query(int L, int R) const {110 const int i = __lg(R - L + 1);111 return fn(st[i][L], st[i][R - (1 << i) + 1]); 112 }113 114 private:115 vector<vector<int64_t>> st;116 const function<int (int, int)>& fn;117 };118};119 120121122123const int NEG_INF = numeric_limits<int>::min();124const int POS_INF = numeric_limits<int>::max();125class Solution3 {126public:127 long long maxTotalValue(vector<int>& nums, int k) {128 SegmentTreeMin st_min(nums);129 SegmentTreeMax st_max(nums);130 using P = pair<int, pair<int, int>>;131 vector<P> arr(size(nums));132 for (int i = 0; i < size(nums); ++i) {133 arr[i] = {st_max.query(i, size(nums) - 1) - st_min.query(i, size(nums) - 1), {i, size(nums) - 1}};134 }135 priority_queue<P> max_heap(cbegin(arr), cend(arr));136 int64_t result = 0;137 for (int _ = 0; _ < k; ++_) {138 const auto [v, i_j] = max_heap.top(); max_heap.pop();139 const auto& [i, j] = i_j;140 result += v;141 if (i <= j - 1) {142 max_heap.push({st_max.query(i, j - 1) - st_min.query(i, j - 1), {i, j - 1}});143 }144 }145 return result;146 }147 148private:149 class SegmentTreeMax {150 public:151 explicit SegmentTreeMax(const auto& nums)152 : base_(size(nums) > 1 ? 1 << (__lg(size(nums) - 1) + 1) : 1),153 tree(size(nums) > 1 ? 1 << (__lg(size(nums) - 1) + 2) : 2, NEG_INF) {154 for (int i = base_; i < base_ + size(nums); ++i) {155 tree[i] = nums[i - base_];156 }157 for (int i = base_ - 1; i >= 1; --i) {158 tree[i] = max(tree[i << 1], tree[(i << 1) + 1]);159 }160 }161 162 int query(int L, int R) {163 if (L > R) {164 return NEG_INF;165 }166 L += base_;167 R += base_;168 int left = NEG_INF, right = NEG_INF;169 for (; L <= R; L >>= 1, R >>= 1) {170 if ((L & 1) == 1) {171 left = max(left, tree[L++]);172 }173 if ((R & 1) == 0) {174 right = max(tree[R--], right);175 }176 }177 return max(left, right);178 }179 180 vector<int> tree;181 int base_;182 };183 184 class SegmentTreeMin {185 public:186 explicit SegmentTreeMin(const auto& nums)187 : base_(size(nums) > 1 ? 1 << (__lg(size(nums) - 1) + 1) : 1),188 tree(size(nums) > 1 ? 1 << (__lg(size(nums) - 1) + 2) : 2, POS_INF) {189 for (int i = base_; i < base_ + size(nums); ++i) {190 tree[i] = nums[i - base_];191 }192 for (int i = base_ - 1; i >= 1; --i) {193 tree[i] = min(tree[i << 1], tree[(i << 1) + 1]);194 }195 }196 197 int query(int L, int R) {198 if (L > R) {199 return POS_INF;200 }201 L += base_;202 R += base_;203 int left = POS_INF, right = POS_INF;204 for (; L <= R; L >>= 1, R >>= 1) {205 if ((L & 1) == 1) {206 left = min(left, tree[L++]);207 }208 if ((R & 1) == 0) {209 right = min(tree[R--], right);210 }211 }212 return min(left, right);213 }214 215 vector<int> tree;216 int base_;217 };218};219