Mainly record the On preprocessing, O1 takes the prefix sum of any interval prefix sum
topic
6077. The wizard's total power and
problem solving ideas
Greedy considers from small to large, each calculation is based on ai a_iaiContribution at minimum.
Let's look at specific examples:
- Consider a 2 a_2a2Contribution at minimum
interval [ 1 , 2 ] , [ 1 , 3 ] , [ 1 , 4 ] , [ 1 , 5 ] , [ 2 , 2 ] , [ 2 , 3 ] , [ 2 , 4 ] , [ 2 , 5 ] [1,2],[1,3],[1,4],[1,5],[2,2],[2,3],[2,4],[2,5] ][1,2],[1,3],[1,4],[1,5],[2,2],[2,3],[2,4],[2,5] - Consider a 4 a_4a4Contribution at minimum
interval [ 3 , 4 ] , [ 4 , 4 ] , [ 4 , 5 ] , [ 3 , 5 ] [3,4],[4,4],[4,5],[3 ,5][3,4],[4,4],[4,5],[3,5 ]
If we calculate the interval[1,4][1,4][1,4 ] or[2, 4] [2,4][2,4 ] , then the contribution calculation in 1 is repeated. Therefore, each calculationof ai a_iaiWhen the contribution, the left endpoint does not exceed the previous value and ai a_iaisame position, right endpoint to nnn , but this is not enough, we also need to ensure that the minimum value of these intervals isai a_iai。 - Consider a 3 a_3a3Contribution at minimum
interval [ 3 , 3 ] [3,3][3,3 ] legal, because the previously enumeratedai a_iaiare less than the current value, the array will be split.
Next consider how to calculate the interval contribution. It is impossible for us to enumerate all the intervals, so it will time out to observe the contribution in the above step 1.
easy to spot, with ai a_iaiWhen it is the minimum value, the contribution times of the left element are 1 time, 2 times, 3 times. . . . . . 1 time, 2 times, 3 times... ...1 time ,2 times ,3 times . . . . . , the number of contributions of the left element is. . . . . 3 times, 2 times, 1 time... ...3 times, 2 times, 1 time. . . . . 3 times , _2 times ,primary , aia_iaiThe number of contributions by itself is ( numleft + 1 ) × ( numright + 1 ) (num_{left}+1)\times(num_{right}+1)(numleft+1)×(numright+1 ) times. You only need to determine the left and right endpoints of the interval, you can directly calculatethe ai a_iaiContribution of all intervals for the minimum.
a i a_i aiThe number of contributions on both sides satisfies the prefix sum law of the prefix sum . The right part is the prefix sum of the prefix sums from left to right. The left part is the suffix sum of the right-to-left suffix sum. How to quickly calculate the prefix sum of the prefix sum of any interval?
Look at the picture below.
Initialization: s 0 = ss 0 = 0 s_0 = ss_0=0s0=ss0=0
pre-harmonization:si = si − 1 + ai s_i = s_{i-1}+a_isi=si−1+ai
Prefix sum of prefix sums: ssi = ssi − 1 + si ss_i = ss_{i-1}+s_issi=ssi−1+si
in conclusion:
s s l , r = s s r − s s l − 1 − ( r − l + 1 ) × s l − 1 ss_{l,r}=ss_{r}-ss_{l-1}-(r-l+1)\times s_{l-1} ssl,r=ssr−ssl−1−(r−l+1)×sl−1
It is easy to verify the correctness of the conclusion, so I won't repeat it here.
In this way, we can O ( n ) O(n)After O ( n ) preprocessing,O ( 1 ) O(1)O ( 1 ) to get the prefix sum ofany interval's.
The suffix is the same.
AC code
const long long N = 1e5 + 5;
const long long mod = 1e9 + 7;
class Solution
{
public:
map<long long, vector<long long>> pos;
long long pre[N], suf[N], ppre[N], ssuf[N];
set<long long> st;
set<long long> vis;
long long n;
void init_ss(vector<int> &a)
{
int n = a.size() - 1;
for (int i = 1; i <= n; i++)
pre[i] = pre[i - 1] + a[i];
for (int i = 1; i <= n; i++)
ppre[i] = (ppre[i - 1] + pre[i]) % mod;
for (int i = n; i >= 1; i--)
suf[i] = suf[i + 1] + a[i];
for (int i = n; i >= 1; i--)
ssuf[i] = (ssuf[i + 1] + suf[i]) % mod;
}
long long getlr(int l, int r)
{
long long len = r - l + 1;
return (ppre[r] - (ppre[l - 1] + pre[l - 1] * len) % mod + mod) % mod;
}
long long getrl(int r, int l)
{
long long len = r - l + 1;
return (ssuf[l] - (ssuf[r + 1] + suf[r + 1] * len) % mod + mod) % mod;
}
long long totalStrength(vector<int> &a)
{
n = a.size();
a.insert(a.begin(), -1);
init_ss(a);
vis.insert(0);
vis.insert(n + 1);
for (long long i = 1; i <= n; i++)
{
st.insert(a[i]);
pos[a[i]].emplace_back(i);
}
long long ans = 0;
for (auto val : st)
{
long long m = pos[val].size();
for (long long i = 0; i < m; i++)
{
long long p = pos[val][i];
auto iter = vis.upper_bound(p);
long long rr = (*iter) - 1;
iter--;
long long ll = (*iter) + 1;
long long lenL = p - ll + 1;
long long lenR = rr - p + 1;
long long num, v;
num = lenL;
v = getlr(p, rr);
ans = (ans + num * v % mod * val) % mod;
num = lenR;
v = getrl(p, ll);
ans = (ans + num * v % mod * val) % mod;
num = lenR * lenL % mod;
v = val;
ans = (ans - num * v % mod * val % mod + mod) % mod; //减去重复贡献
vis.insert(p);
}
}
return ans;
}
};