树状数组区间修改 poj3468(A Simple Problem with Integers)
http://poj.org/problem?id=3468
题意:
给出n,q <1e6
n个整数-1000000000 ≤ Ai ≤ 1000000000
q个命令:"C a b c"a到b区间全部+c 或 "Q a b" 输出a到b区间的和
-----------------------------------------------------------
树状数组的区间修改+区间查询:
1 #include <stdio.h> 2 #include <math.h> 3 #include <string.h> 4 #include <algorithm> 5 #include <iostream> 6 #include <queue> 7 #include <stack> 8 #include <functional> 9 #define INF 0x3f3f3f3f 10 #define N 100010 11 #define lowbit(a) ((a)&(-a)) 12 using namespace std; 13 typedef long long ll; 14 15 ll sum[N], d[N], di[N]; 16 17 //区间修改 18 void _update(ll *arr, ll pos, ll x){ 19 while (pos <= N){ 20 arr[pos] += x; 21 pos += lowbit(pos); 22 } 23 } 24 void add(ll l, ll r, ll x){ 25 _update(d, l, x); 26 _update(d, r + 1, -x); 27 _update(di, l, x*l); 28 _update(di, r + 1, -x*(r + 1)); 29 } 30 //区间查询 31 ll _sum(ll *arr, ll pos){ 32 ll temp = 0ll; 33 while (pos){ 34 temp += arr[pos]; 35 pos -= lowbit(pos); 36 } 37 return temp; 38 } 39 ll getsum(ll pos){ 40 return sum[pos] + _sum(d, pos)*(pos + 1) - _sum(di, pos); 41 } 42 43 int main(){ 44 ll l, r, x; 45 char ch; 46 int n, m; 47 48 while (~scanf("%d %d", &n, &m)){ 49 sum[0] = 0; 50 for (int i = 1; i <= n; i++){ 51 scanf("%lld", &x); 52 sum[i] = sum[i - 1] + x; 53 } 54 memset(d, 0, sizeof(d)); 55 memset(di, 0, sizeof(di)); 56 while (m--){ 57 while ((ch = getchar()) == '\n'); 58 if (ch == 'Q'){ 59 scanf("%lld %lld", &l, &r); 60 printf("%lld\n", getsum(r) - getsum(l - 1)); 61 } 62 else{ 63 scanf("%lld %lld %lld", &l, &r, &x); 64 add(l, r, x); 65 } 66 } 67 } 68 return 0; 69 }