题目类型 线段树 - 区间修改
题目意思
给出最多100000个数 现在有最多100000个操作
操作1 把 区间 [L,R]中的数加上一个数c
操作2 询问区间 [L,R]中的数的和是多少
解题方法
区间修改的线段树
注意懒惰标记的使用就行了
参考代码 - 有疑问的地方在下方留言 看到会尽快回复的
#include <iostream> #include <cstdio> #include <cstring> using namespace std; #define ls (rt<<1) #define rs ((rt<<1)|1) #define mid ((l+r)>>1) typedef long long LL; const int maxn = 1e5 + 10; LL sum[maxn*4], add[maxn*4]; int A[maxn]; void build(int rt, int l, int r) { if(l == r) { sum[rt] = A[l]; return ; } build(ls, l, mid); build(rs, mid + 1, r); sum[rt] = sum[ls] + sum[rs]; } void pushdown(int rt, int l, int r) { if(l != r) { if(add[rt]) { sum[ls] += (mid - l + 1) * add[rt]; add[ls] += add[rt]; sum[rs] += (r - mid) * add[rt]; add[rs] += add[rt]; add[rt] = 0; } } } void update(int rt, int l, int r, int L, int R, int c) { pushdown(rt, l, r); if(l == L && r == R) { sum[rt]+= (r-l+1)*c; add[rt] = c; return ; } if(R <= mid) update(ls, l, mid, L, R, c); else if(L > mid) update(rs, mid + 1, r, L, R, c); else update(ls, l, mid, L, mid, c), update(rs, mid + 1, r, mid + 1, R, c); sum[rt] = sum[ls] + sum[rs]; } LL query(int rt, int l, int r, int L, int R) { pushdown(rt, l, r); if(l == L && r == R) return sum[rt]; if(R <= mid) return query(ls, l, mid, L, R); else if(L > mid) return query(rs, mid + 1, r, L, R); else return query(ls, l, mid, L, mid) + query(rs, mid + 1, r, mid + 1, R); sum[rt] = sum[ls] + sum[rs]; } int main() { freopen("in", "r", stdin); int n, m; while(scanf("%d%d", &n, &m) != EOF) { for( int i=0; i<n; i++ ) scanf("%d", &A[i]); build(1, 0, n); for( int i=0; i<m; i++ ) { char str[10]; scanf("%s", str); if(str[0] == 'Q') { int l, r; scanf("%d%d", &l, &r); LL ans = query(1, 0, n, l-1, r-1); cout<<ans<<endl; } else { int l, r, c; scanf("%d%d%d", &l, &r, &c); update(1, 0, n, l-1, r-1, c); } } } return 0; }