Editorial for Ripple Effect
Remember to use this editorial only when stuck, and not to copy-paste code from it. Please be respectful to the problem author and editorialist.
Submitting an official solution before solving the problem yourself is a bannable offence.
Submitting an official solution before solving the problem yourself is a bannable offence.
Author:
Let be the answer to this problem. We know:
.
We can rewrite as:
.
This means we can calculate the total contribution of each element of separately—once for when it acts as the maximum in a subarray, and once for when it acts as the minimum.
Step 1 — Contribution as Minimum
For each , find:
= index of the closest element to the left of
that is strictly smaller than
(or
0
if none exists),= index of the closest element to the right of
that is smaller or equal to
(or
n+1
if none exists).
In all subarrays of the form with
that include
,
is the minimum element.
The number of such subarrays is:
.
Thus, contributes:
to
.
Step 2 — Contribution as Maximum
Similarly, find:
= index of the closest element to the left of
that is strictly greater than
(or
0
if none exists),= index of the closest element to the right of
that is greater or equal to
(or
n+1
if none exists).
The number of subarrays where is the maximum is:
.
Thus, contributes:
to
.
We compute by summing the contributions of all elements for both their maximum and minimum roles:
.
Both and
can be found in
using monotonic stacks.
C++ Solution:
#include <bits/stdc++.h>
using namespace std;
int main() {
int n;
cin >> n;
vector<int> arr(n);
for (auto& x: arr) cin >> x;
vector<long long> lMin(n), rMin(n);
vector<long long> lMax(n), rMax(n);
stack<int> s;
for (int i = 0; i < n; i++) {
while (!s.empty() && arr[s.top()] >= arr[i])
s.pop();
lMin[i] = s.empty() ? -1 : s.top();
s.push(i);
}
while (!s.empty()) s.pop();
for (int i = n - 1; i >= 0; i--) {
while (!s.empty() && arr[s.top()] > arr[i])
s.pop();
rMin[i] = s.empty() ? n : s.top();
s.push(i);
}
while (!s.empty()) s.pop();
for (int i = 0; i < n; i++) {
while (!s.empty() && arr[s.top()] <= arr[i])
s.pop();
lMax[i] = s.empty() ? -1 : s.top();
s.push(i);
}
while (!s.empty()) s.pop();
for (int i = n - 1; i >= 0; i--) {
while (!s.empty() && arr[s.top()] < arr[i])
s.pop();
rMax[i] = s.empty() ? n : s.top();
s.push(i);
}
long long result = 0;
for (int i = 0; i < n; i++) {
// Count subarrays where arr[i] is maximum
long long maxCount = (long long)(i - lMax[i]) * (rMax[i] - i);
// Count subarrays where arr[i] is minimum
long long minCount = (long long)(i - lMin[i]) * (rMin[i] - i);
result += (long long)arr[i] * (maxCount - minCount);
}
cout << result << endl;
}
Python Solution:
n = int(input())
A = list(map(int, input().split()))
lMin, lMax, rMin, rMax = [[0 for _ in range(n)] for _ in range(4)]
maxS, minS = [], []
for i in range(n):
while maxS and A[maxS[-1]] <= A[i]:
maxS.pop()
while minS and A[minS[-1]] >= A[i]:
minS.pop()
lMin[i] = minS[-1] if minS else -1
lMax[i] = maxS[-1] if maxS else -1
maxS.append(i)
minS.append(i)
maxS.clear()
minS.clear()
for i in range(n)[::-1]:
while maxS and A[maxS[-1]] < A[i]:
maxS.pop()
while minS and A[minS[-1]] > A[i]:
minS.pop()
rMin[i] = minS[-1] if minS else n
rMax[i] = maxS[-1] if maxS else n
maxS.append(i)
minS.append(i)
res = 0
# Add the maxsum and subtract the minsum
for i, (l, r) in enumerate(zip(lMax, rMax)):
res += A[i]*(i-l)*(r-i)
for i, (l,r) in enumerate(zip(lMin, rMin)):
res -= A[i]*(i-l)*(r-i)
print(res)
Comments