题目链接:Gym 237040F 线段树:区间修改,区间查询
题目大意:
题解:
线段树或者树状数组模板题。
\(cin,cout\)貌似会超时,要用\(scanf,printf\)或者快读。
线段树
考察对\(lazy\)标记的使用。
#include <cstdio>
#include <cstring>
#include <iostream>
using namespace std;
#define ll long long
struct Tree {
ll num, left, right, lazy;
} tree[4000005];
ll read() {
char x = getchar();
ll ans = 0, f = 1;
while (!isdigit(x)) {
if (x == '-') f = -1;
x = getchar();
}
while (isdigit(x)) {
ans = (ans << 3) + (ans << 1) + (x ^ 48);
x = getchar();
}
return ans * f;
}
void build(ll k, ll l, ll r) {
tree[k].lazy = 0, tree[k].left = l, tree[k].right = r;
if (l == r) {
tree[k].num = read();
return;
}
ll mid = l + r >> 1;
build(k << 1, l, mid);
build((k << 1) | 1, mid + 1, r);
tree[k].num = tree[k << 1].num + tree[(k << 1) | 1].num;
}
void push_down(ll k) {
tree[k << 1].lazy += tree[k].lazy;
tree[(k << 1) | 1].lazy += tree[k].lazy;
tree[k << 1].num += tree[k].lazy * (tree[k << 1].right - tree[k << 1].left + 1);
tree[(k << 1) | 1].num += tree[k].lazy * (tree[(k << 1) | 1].right - tree[(k << 1) | 1].left + 1);
tree[k].lazy = 0;
}
void update(ll k, ll l, ll r, ll add) {
if (tree[k].left >= l && tree[k].right <= r) {
tree[k].num += add * (tree[k].right - tree[k].left + 1);
tree[k].lazy += add;
return;
}
if (tree[k].lazy) push_down(k);
ll mid = tree[k].left + tree[k].right >> 1;
if (l <= mid) update(k << 1, l, r, add);
if (r > mid) update((k << 1) | 1, l, r, add);
tree[k].num = tree[k << 1].num + tree[(k << 1) | 1].num;
}
ll query(ll k, ll l, ll r) {
if (tree[k].left >= l && tree[k].right <= r) {
return tree[k].num;
}
if (tree[k].lazy) push_down(k);
ll mid = tree[k].left + tree[k].right >> 1;
ll ans = 0;
if (l <= mid) ans += query(k << 1, l, r);
if (r > mid) ans += query((k << 1) | 1, l, r);
return ans;
}
int main() {
ll n, m, add, x, y, act;
n = read(), m = read();
build(1, 1, n);
while (m--) {
act = read(), x = read(), y = read();
if (act == 1) {
add = read();
update(1, x, y, add);
}
if (act == 2) {
printf("%lld\n", query(1, x, y));
}
}
return 0;
}
树状数组
#include <cstdio>
#include <iostream>
using namespace std;
long long n, q, bit0[1000010], bit1[1000010];
void updata(long long *bit, long long x, long long add) {
while (x <= n) {
bit[x] += add;
x += x & -x;
}
}
long long getSum(long long *bit, long long x) {
long long sum = 0;
while (x > 0) {
sum += bit[x];
x -= x & -x;
}
return sum;
}
int main() {
scanf("%lld%lld", &n, &q);
long long act, add, l, r;
for (int i = 1; i <= n; ++i) {
scanf("%lld", &add);
updata(bit0, i, add);
}
for (int i = 1; i <= q; ++i) {
scanf("%lld", &act);
if (act == 1) {
scanf("%lld%lld%lld", &l, &r, &add);
updata(bit1, l, add);
updata(bit0, l, -add * (l - 1));
updata(bit1, r + 1, -add);
updata(bit0, r + 1, add * r);
} else {
scanf("%lld%lld", &l, &r);
long long ans = 0;
ans += getSum(bit1, r) * r + getSum(bit0, r);
ans -= getSum(bit1, l - 1) * (l - 1) + getSum(bit0, l - 1);
printf("%lld\n", ans);
}
}
return 0;
}