这是一道模板题。给定数列 a[1], a[2], \dots, a[n] ,
你需要依次进行 q 个操作,
操作有两类:
1 i x:给定 i,x ,将 a[i] 加上 x ;
2 l r:给定 l,r ,求 \sum_{i=l}^ra[i] 的值(换言之,求 a[l]+a[l+1]+\dots+a[r] 的值)。
第一行包含 2 个正整数 n,q ,表示数列长度和询问个数。保证 1\le n,q\le 10^6 。
第二行 n 个整数 a[1], a[2], \dots, a[n] ,表示初始数列。保证 |a[i]|\le 10^6 。
接下来 q 行,每行一个操作,为以下两种之一:1 i x:给定 i,x ,将 a[i]加上 x;2 l r:给定 l,r ,求 \sum_{i=l}的值。保证 1\le l\le r\le n, |x|\le 10^6 。
对于每个 2 l r 操作输出一行,每行有一个整数,表示所求的结果。
样例输入
3 2
1 2 3
1 2 0
2 1 3
样例输出
6
对于所有数据, 1\le n,q\le 10^6, |a[i]|\le 10^6 , 1\le l\le r\le n, |x|\le 10^6 。
思路: 线段树的模板题,也可以用树状数组解决,树状数组内存更小。
#include
#include
#include
#include
#define ls(x) x << 1 //2 * x
#define rs(x) x << 1 | 1 //2 * x + 1
using namespace std;
typedef long long ll;
const int maxn = 1e6 + 5;
int n, m;
ll a[maxn], ans[4 * maxn], add[4 * maxn]; //开4倍大小的数组,add是标记,ans是答案
void push_up(int x)
{
ans[x] = ans[ls(x)] + ans[rs(x)];
}
//优化输入
inline int read()
{
int s = 0, w = 1;
char ch = getchar();
while (ch < '0' || ch > '9')
{
if (ch == '-')
w = -1;
ch = getchar();
}
while (ch >= '0' && ch <= '9')
{
s = s * 10 + ch - '0';
ch = getchar();
}
return s * w;
}
//建树
void build(int x, int l, int r)
{
add[x] = 0;
if (l == r)
{
ans[x] = a[l];
return;
}
int mid = (l + r) >> 1;
build(ls(x), l, mid);
build(rs(x), mid + 1, r);
push_up(x);
}
//标记下传
void push_down(int x, int l, int r)
{
int mid = (l + r) >> 1;
add[ls(x)] += add[x];
add[rs(x)] += add[x];
ans[ls(x)] += add[x] * (mid - l + 1);
ans[rs(x)] += add[x] * (r - mid);
add[x] = 0;
}
//更改
void change(int nl, int nr, int l, int r, int x, ll k)
{
if (nl <= l && r <= nr)
{
ans[x] += k * (r - l + 1);
add[x] += k;
return;
}
push_down(x, l, r);
int mid = (l + r) >> 1;
if (nl <= mid)change(nl, nr, l, mid, ls(x), k);
if (mid + 1 <= nr)change(nl, nr, mid + 1, r, rs(x), k);
push_up(x);
}
//查询
ll query(int ql, int qr, int l, int r, int x)
{
ll res = 0;
if (ql <= l && r <= qr)return ans[x];
int mid = (l + r) >> 1;
push_down(x, l, r);
if (ql <= mid)res += query(ql, qr, l, mid, ls(x));
if (mid + 1 <= qr)res += query(ql, qr, mid + 1, r, rs(x));
return res;
}
int main()
{
n = read();
m = read();
for (int i = 1; i <= n; ++i)
a[i] = read();
build(1, 1, n);
while (m--)
{
int judge = read();
int x = read();
int y = read();
ll k;
if (judge == 1)
change(x, x, 1, n, 1, y);
else if (judge == 2)
printf("%lld\n", query(x, y, 1, n, 1));
}
return 0;
}