AT_abc423_e [ABC423E] Sum of Subarrays 题解

题目传送门

思路

我们可以将题目中的式子转化为:

\[\begin{aligned} \sum_{[l,r] \in [L,R]} \sum_{i \in [l,r]} a_i \end{aligned} \]

考虑有多少区间 \([l,r]\)\(i\) 有贡献。我们发现很显然,\(l \le i\)\(r \ge i\),即 \(l \in [L,i], r \in [i, R]\)。根据乘法原理可得有 \((i - L + 1) \times (R - i + 1)\) 个区间。故对于 \(i\) 而言,答案即为 \((i - L + 1) \times (R - i + 1) \times a_i\)

所以最终答案为:

\[\begin{aligned} \sum_{i \in [L,R]} ((i - L + 1) \times (R - i + 1) \times a_i) \end{aligned} \]

可这样的时间复杂度为 \(\mathcal{O}(nq)\),无法通过,考虑优化。我们发现:

\[\begin{aligned} 原式 = \sum_{i \in [L,R]} (i \times a_i) \times (L + R) - a_i \times (L \times R + L - R - 1) - i^2 \times a_i \end{aligned} \]

只有 \(i\)\(a_i\) 为变量,故分别维护 \(a_i\)\(i \times a_i\)\(i^2 \times a_i\) 的前缀和即可。时间复杂度 \(\mathcal{O}(n + q)\),可以通过此题。

代码

#include <bits/stdc++.h>
#define int long long
using namespace std;

const int N = 3e5 + 5;

int n, q;
int a[N], sum1[N], sum2[N], sum3[N];

signed main()
{
	scanf("%lld%lld", &n, &q);
	for (int i = 1; i <= n; i++)
		scanf("%lld", &a[i]);
	for (int i = 1; i <= n; i++)
	{
		sum1[i] = sum1[i - 1] + a[i];
		sum2[i] = sum2[i - 1] + i * a[i];
		sum3[i] = sum3[i - 1] + i * i * a[i];
	}
	while (q--)
	{
		int l, r;
		scanf("%lld%lld", &l, &r);
		int ans = (sum2[r] - sum2[l - 1]) * (l + r) - (sum1[r] - sum1[l - 1]) * (l * r + l - r - 1) - (sum3[r] - sum3[l - 1]);
		printf("%lld\n", ans);
	}
	return 0;
}
posted @ 2026-01-04 16:47  lucasincyber  阅读(1)  评论(0)    收藏  举报