poj3468(树状数组:区间修改 区间求和)

题目:

题意:

代码:

/*  树状数组:区间修改 区间求和 
10 5
1 2 3 4 5 6 7 8 9 10
Q 4 4
Q 1 10
Q 2 4
C 3 6 3
Q 2 4
输入n个数,m次查询;
Q p q         输出 a[p] + …… + a[q] = ?
C p q v      a[p] += v, a[p+1]+=v, ……, a[q] += v; 
解法:维护两个树状数组
ans += (long long)(q+1)*s.getsum(q) - d.getsum(q);
ans -= (long long)p*s.getsum(p-1) - d.getsum(p-1); 
没看懂…… 
*/
#include <cstdio>
#include <cstdlib>
#include <climits>
#include <cstring>
#include <cmath>

#include <algorithm>
#include <iostream>
#include <queue>
#include <map>
using namespace std;
typedef long long ll;
#define INF (INT_MAX/10)
#define SQR(x) ((x)*(x))
#define rep(i, n) for (int i=0; i<(n); ++i)
#define repf(i, a, b) for (int i=(a); i<=(b); ++i)
#define repd(i, a, b) for (int i=(a); i>=(b); --i)
#define clr(ar,val) memset(ar, val, sizeof(ar))
#define N 20000
const int maxn = 100010;
template <int SZ>
class BIT{
    long long c[SZ*3+10];
public :
    void clear(){clr(c,0);}
    long long getsum(int x){
        long long s=0;
        while(x>0)
            s+=c[x], x-=x&-x;
        return s;
    }
    void update(int x, int n){
        while(x<=SZ)
            c[x]+=n,x+=x&-x;
    }
};

BIT <maxn> s, d;
long long a[maxn];
int main(){
	int n, m;
	char c[10];
	int p, q, v;
	while(~scanf("%d%d",&n,&m)){
		s.clear();
		d.clear();
		for(int i = 1; i <= n; i ++) scanf("%lld",a+i);
		for(int i = 2; i <= n; i ++) a[i] += a[i-1];
		for(int i = 0; i < m; i ++){
			scanf("%s%d%d",c,&p,&q);
			if( c[0] == 'C' ){
				scanf("%d",&v);
				s.update(p,v);
				s.update(q+1,-v);
				d.update(p,v*p);
				d.update(q+1,-v*(q+1));
			}
			else if( c[0] == 'Q'){
				long long ans = a[q] - a[p-1];
				ans += (long long)(q+1)*s.getsum(q) - d.getsum(q);
            	ans -= (long long)p*s.getsum(p-1) - d.getsum(p-1);
            	printf("%lld\n",ans);
			}
		}
	}
	return 0;
}


你可能感兴趣的:(poj3468(树状数组:区间修改 区间求和))