Leetcode's 294th weekly game wizard's total power sum - maintain the prefix sum of the prefix sum

Mainly record the On preprocessing, O1 takes the prefix sum of any interval prefix sum

topic

6077. The wizard's total power and

insert image description here

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:

insert image description here

  1. 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]
  2. 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
  3. 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.

insert image description here
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.
insert image description here
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=si1+ai
Prefix sum of prefix sums: ssi = ssi − 1 + si ss_i = ss_{i-1}+s_issi=ssi1+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=ssrssl1(rl+1)×sl1

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;
	}
};

Guess you like

Origin blog.csdn.net/hesorchen/article/details/124912821
Recommended