摘要:
節點裏需要記錄區間的和,區間的增量。以保證Insert和Calculate都是log(n)的,話說還不是很懂,看別人的代碼過的。。
#include <iostream>
#include <stdio.h>
using namespace std;
const int size = 100000;
typedef struct Node{
int left;
int right;
long long sum;
long long mod;
Node * left_child;
Node * right_child;
void Construct(int, int);
void Insert(int, int, int);
long long Calculate(int, int);
}Node;
Node sTree[size * 3];
Node *root = &sTree[0];
int len = 1;
int input[size+1] = {0};
void Node::Construct(int l, int r)
{
left = l;
right = r;
sum = 0;
mod = 0;
if( l == r ){
sum = input[l];
left_child = right_child = NULL;
return;
}
left_child = &sTree[len++];
right_child = &sTree[len++];
int mid = (left + right) >> 1;
left_child->Construct(l, mid);
right_child->Construct(mid+1, r);
sum = left_child->sum + right_child->sum;
}
void Node::Insert(int l, int r, int value)
{
//cout << "insert:" << left << "," << right << "/t" << l << "," << r << endl;
if( l==left && r==right){
mod += value;
return;
}
sum += ( r - l + 1) * value;
int mid = (left + right) >> 1;
if( l > mid ){
right_child->Insert(l, r, value);
return;
}
if( r <= mid ){
left_child->Insert(l, r, value);
return;
}
left_child->Insert(l, mid, value);
right_child->Insert(mid+1, r, value);
}
long long Node::Calculate(int l, int r)
{
//cout << "right calculate:" << left << "," << right << "/t" << l << "," << r << endl;
if( left==l && right==r){
return sum + (right-left+1) * mod;
}
if( mod != 0 ){
left_child->mod += mod;
right_child->mod += mod;
sum += (right-left+1)*mod;
mod = 0;
}
int mid = (left + right) >> 1;
//cout << mid << endl;
if( l > mid ){
return right_child->Calculate(l, r);
}
if( r <= mid){
return left_child->Calculate(l, r);
}
return left_child->Calculate(l, mid) + right_child->Calculate(mid+1, r);
}
int main()
{
int N, Q;
scanf("%d%d", &N, &Q);
for(int i=1; i<=N; i++){
scanf("%d", &input[i]);
}
len = 1;
root->Construct(1, N);
getchar();
for(int i=1; i<=Q; i++){
char ch = getchar();
int left, right, value;
scanf("%d%d", &left, &right);
if(ch == 'Q'){
//cout << "Calculate:" << left << "," << right << endl;
printf("%lld/n", root->Calculate(left, right));
}else{
scanf("%d", &value);
//cout << "Insert:" << left << "," << right << "," << value << endl;
root->Insert(left, right, value);
}
getchar();
}
return 0;
}