线段树 P3372【区间修改 区间查询】
题目
代码
树状数组方法
#include<iostream> #include<cstdio> using namespace std; long long a[100001], c[100001],sum[100001]; int n, m; long long lowbit(long long x) { return x&(-x); } void update(long long i, long long k) { long long x = i; while (i <= n) { c[i] += k; sum[i] += (x-1)*k; i += lowbit(i); } } long long getsum(long long i) { long long res = 0; long long x = i; while (i > 0) { res += c[i]*x-sum[i]; i -= lowbit(i); } return res; } int main() { long long type,x,y,k; scanf("%d %d", &n, &m); for (int i = 1; i <= n; i++) { scanf("%lld", &a[i]); update(i, a[i]-a[i-1]); } for (int i = 0; i < m; i++) { scanf("%lld %lld %lld", &type,&x,&y); if (type == 1) { scanf("%lld", &k); update(x, k); update(y + 1, -k); } else { printf("%lld\n", getsum(y) - getsum(x - 1)); } } }
开始int 溢出,改为long long通过
线段树方法
#include<iostream> #include<algorithm> #include<cstdio> using namespace std; #define MAX 100001 #define INF 0x3f3f3f3f long long a[MAX], c[MAX << 2], lazy[MAX << 2];//空间,一般会开到4*n的空间防止RE。 int n, m; void build(long long k, int l, int r) { if (l == r)//如果是最后的叶子节点,就直接赋值 c[k] = a[l]; else { int m = l + ((r - l) >> 1);//注意这里的括号,进行优先级的处理 build(k << 1, l, m);//不是的话就递归 build(k << 1 | 1, m + 1, r); c[k] = c[k << 1] + c[k << 1 | 1];//由于不是最后的叶子节点,所以一定有左右子节点,所以此节点的值就是左右子节点较大的值 } } void pushdown(long long k, int l, int r) { if (lazy[k]) { int m = (l + r) >> 1; lazy[k << 1] += lazy[k]; lazy[k << 1 | 1] += lazy[k]; c[k << 1] += lazy[k] * (m - l + 1); c[k << 1 | 1] += lazy[k] * (r - (m + 1) + 1); lazy[k] = 0; } } void update(int L, int R, int v, int l, int r, long long k) { if (L <= l&&R >= r) { c[k] += (r - l + 1)* v; lazy[k] += v; } else { pushdown(k, l, r); int m = l + ((r - l) >> 1); if (L <= m) update(L, R, v, l, m, k << 1); if (R >m) update(L, R, v, m + 1, r, k << 1 | 1); c[k] = c[k << 1] + c[k << 1 | 1]; } } long long query(int L, int R, int l, int r, long long k) { if (L <= l&&R >= r) return c[k]; else { pushdown(k, l, r); /**每次都需要更新子树的Lazy标记*/ long long res = 0; int m = l + ((r - l) >> 1); if (L <= m)res += query(L, R, l, m, k << 1); if (m < R)res += query(L, R, m + 1, r, k << 1 | 1); return res; } } int main() { long long type,x,y,k; scanf("%d %d", &n, &m); for (int i = 1; i <= n; i++) scanf("%lld", &a[i]); build(1, 1, n); for (int i = 0; i < m; i++) { scanf("%lld %lld %lld", &type,&x,&y); if (type == 1) { scanf("%lld", &k); update(x, y, k, 1, n, 1); } else { printf("%lld\n", query(x,y,1,n,1)); } } }