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

浙公网安备 33010602011771号