3468:A Simple Problem with Integers

問題文
http://poj.org/problem?id=3468






































蟻本でも紹介されている問題。
セグメント木を実装した。各節点は次の2つのデータをもつ。
whole[ ] その節点の区間全体に一様に加えられた値
part[ ] その節点の区間に一様でなく加えられた値

#include<iostream>
#include<vector>
#include<algorithm>
#include<string>
#include<cstdio>
#define nmax (1<<18)

using namespace std;

typedef long long ll;

int n;
ll whole[nmax],part[nmax];

void add(int a,int b,int x,int k,int l,int r){
	
	if(a<=l && r<=b)whole[k]+=x;
	else if(l<b && a<r){
		add(a,b,x,k*2+1,l,(l+r)/2);
		add(a,b,x,k*2+2,(l+r)/2,r);
		part[k]+=(min(b,r)-max(a,l))*x;
	}
}

ll sum(int a,int b,int k,int l,int r){
	if(b<=l || r<=a)return 0;
	if(a<=l && r<=b)return (r-l)*whole[k]+part[k];
	else {
		ll vl=sum(a,b,k*2+1,l,(l+r)/2);
		ll vr=sum(a,b,k*2+2,(l+r)/2,r);
		return vl+vr+(min(b,r)-max(a,l))*whole[k];
	}
}

int main(void){
	
	int m;
	cin >> n >> m;
	
	for(int i=0;i<n;i++){
		int in;
		cin >> in;
		add(i,i+1,in,0,0,n);
	}
	
	for(int i=0;i<m;i++){
		int a,b,x;
		char c;
		scanf(" %c",&c);
		if(c=='Q'){
			scanf("%d %d",&a,&b);
			printf("%lld\n",sum(a-1,b,0,0,n));
		}
		else if(c=='C'){
			scanf("%d %d %d",&a,&b,&x);
			add(a-1,b,x,0,0,n);
		}
	}
	
	return 0;
}