地址 https://www.acwing.com/problem/content/248/
给定长度为N的数列A,然后输入M行操作指令。
第一类指令形如“C l r d”,表示把数列中第l~r个数都加d。
第二类指令形如“Q X”,表示询问数列中第x个数的值。
对于每个询问,输出一个整数表示答案。
输入格式
第一行包含两个整数N和M。
第二行包含N个整数A[i]。
接下来M行表示M条指令,每条指令的格式如题目描述所示。
输出格式
对于每个询问,输出一个整数表示答案。
每个答案占一行。
数据范围
1≤N,M≤1051≤N,M≤105,
|d|≤10000|d|≤10000,
|A[i]|≤1000000000
输入样例:
10 5
1 2 3 4 5 6 7 8 9 10
Q 4
Q 1
Q 2
C 1 6 3
Q 2
输出样例:
4
1
2
5
区间修改 单点询问 利用差分的树状数组
#include <iostream> #include <vector> #include <algorithm> using namespace std; const int N = 100010; typedef long long ll; typedef long long LL; int n, m; int a[N]; ll tr[N]; int lowbit(int x) { return x & -x; } void add(int x, int c) { for (int i = x; i <= n; i += lowbit(i)) tr[i] += c; } ll sum(int x) { ll res = 0; for (int i = x; i; i -= lowbit(i)) res += tr[i]; return res; } int main() { scanf("%d %d", &n, &m); for (int i = 1; i <= n; i++) scanf("%d", &a[i]); for (int i = 1; i <= n; i++) add(i, a[i] - a[i - 1]); while (m--) { char op[2]; int l, r, d; scanf("%s%d",op,&l); if (*op == 'C') { scanf("%d%d", &r, &d); add(l, d); add(r + 1, -d); } else { printf("%lld ",sum(l)); } } return 0; }
线段树 lazy模板
#include <iostream> #include <algorithm> #include <string> using namespace std; /* 给定长度为N的数列A,然后输入M行操作指令。 第一类指令形如“C l r d”,表示把数列中第l~r个数都加d。 第二类指令形如“Q X”,表示询问数列中第x个数的值。 对于每个询问,输出一个整数表示答案。 输入格式 第一行包含两个整数N和M。 第二行包含N个整数A[i]。 接下来M行表示M条指令,每条指令的格式如题目描述所示。 输出格式 对于每个询问,输出一个整数表示答案。 每个答案占一行。 数据范围 1≤N,M≤105, |d|≤10000, |A[i]|≤1000000000 输入样例: 10 5 1 2 3 4 5 6 7 8 9 10 Q 4 Q 1 Q 2 C 1 6 3 Q 2 输出样例: 4 1 2 5 */ const int maxn = 1e5 + 6; int n; int a[maxn]; int q; struct node { int l, r; long long sum, lazy; void update(long long x) { sum += 1ll * (r - l + 1)*x; lazy += x; } }tree[maxn*4]; void push_up(int x) { tree[x].sum = tree[x << 1].sum + tree[x << 1 | 1].sum; } void push_down(int x) { int lazyval = tree[x].lazy; if (lazyval) { tree[x << 1].update(lazyval); tree[x << 1 | 1].update(lazyval); tree[x].lazy = 0; } } void build(int x, int l, int r) { tree[x].l = l; tree[x].r = r; tree[x].sum = tree[x].lazy = 0; if (l == r) { tree[x].sum = a[l]; } else { int mid = (l + r) / 2; build(x << 1, l, mid); build(x << 1 | 1, mid + 1, r); push_up(x); } } void update(int x, int l, int r, long long val) { int L = tree[x].l, R = tree[x].r; if (l <= L && R <= r) { tree[x].update(val); } else { push_down(x); int mid = (L + R) / 2; if (mid >= l) update(x << 1, l, r, val); if (r > mid) update(x << 1 | 1, l, r, val); push_up(x); } } long long query(int x, int l, int r) { int L = tree[x].l, R = tree[x].r; if (l <= L && R <= r) { return tree[x].sum; } else { push_down(x); long long ans = 0; int mid = (L + R) / 2; if (mid >= l) ans += query(x << 1, l, r); if (r > mid) ans += query(x << 1 | 1, l, r); push_up(x); return ans; } } int main() { cin >> n >> q; for (int i = 1; i <= n; i++) { cin >> a[i]; } build(1, 1, n); for (int i = 1; i <= q; i++) { string s; int l, r, d, q; cin >> s; if (s == "Q") { cin >> q; cout << query(1, q, q) << endl; } else { cin >> l >> r >> d; update(1, l, r, d); } } return 0; }