对于形如修改部分区间同时对部分区间求和一类问题,我们可以设原数组 ,差分数组为
,有
当需要在区间 加上
时,修改
和
两点即可,问题是如何快速求出给定区间
的和。也即求形如
的和。将差分数组带入得
于是
- 当
,
- 当
,
- ...
于是原式化为
进一步的有
到这里,我们维护两个差分数组 和
即可快速求出
的区间和,同时支持区间修改。
如果是修改区间 的同时求出单点
,那就更简单了,维护一个差分数组
即可。
#include<iostream>
#define int long long
const int N = 5e5 + 10;
int d[N];
int d_i[N];
inline int lowbit(int x) { return x & -x; }
int query(int n,int d[])
{
int sum = 0;
while (n)
{
sum += d[n];
n -= lowbit(n);
}
return sum;
}
void add(int n, int x,int d[])
{
while (n < N)
{
d[n] += x;
n += lowbit(n);
}
}
signed main()
{
std::ios::sync_with_stdio(false), std::cin.tie(nullptr);
int n, m;
std::cin >> n >> m;
int pre = 0, curr = 0;
for (int i = 1; i <= n; i++)
{
std::cin >> curr;
add(i, curr-pre,d);
add(i, i * (curr - pre), d_i);
pre = curr;
}
int op, x, y, k;
for (int i = 1; i <= m; i++)
{
std::cin >> op;
if (op == 1)
{
std::cin >> x >> y >> k;
add(x, k,d);
add(y + 1, -k,d);
add(x, x * k, d_i);
add(y + 1, -(y + 1) * k, d_i);
}
else
{
std::cin >> x >> y;
std::cout << (y + 1) * query(y, d) - query(y, d_i) -
(x * query(x - 1, d) - query(x - 1, d_i)) << '\n';
}
}
}

京公网安备 11010502036488号