/* THE PROGRAM IS MADE BY PYY */
/*----------------------------------------------------------------------------//
Copyright (c) 2012 panyanyany All rights reserved.
URL : http://poj.org/problem?id=3468
Name : 3468 A Simple Problem with Integers
Date : Sunday, April 15, 2012
Time Stage : 2 hours
Result:
10074419 panyanyany
3468
Accepted 12492K 2047MS C++
3148B 2012-04-15 12:46:56
Test Data :
Review :
普通的线段树方法要超时的,貌似还可以用splay tree(伸展树)。小媛的博客上说要用lazy方法……
//----------------------------------------------------------------------------*/
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <math.h>
#include <vector>
#include <algorithm>
#include <iostream>
#include <queue>
using namespace std ;
#define MEM(a, v) memset (a, v, sizeof (a)) // a for address, v for value
#define max(x, y) ((x) > (y) ? (x) : (y))
#define min(x, y) ((x) < (y) ? (x) : (y))
#define INF (0x3f3f3f3f)
#define MAXN 100010
#define LESN 10002
#define L(x) ((x)<<1)
#define R(x) (((x)<<1)|1)
#define DB /##/
typedef __int64 LL;
struct NODE {
int lf, rh;
LL sm, inc;
};
int q, n;
NODE segTree[MAXN*6]; //开小了一直runtime error
LL inc;
void build(int id, int lf, int rh)
{
segTree[id].lf = lf;
segTree[id].rh = rh;
segTree[id].sm = 0;
segTree[id].inc = 0;
if (lf == rh)
return ;
int mid = (lf + rh) / 2;
build(id<<1, lf, mid);
build((id<<1)|1, mid+1, rh);
}
LL update(int id, int lf, int rh, int val)
{
// 不在当前区间(一般来说都不用判断这个……)
if (segTree[id].lf > rh || segTree[id].rh < lf)
return 0;
// 到达匹配区间,这里不深入更新每一个叶子,因为会超时
if (segTree[id].lf == lf && segTree[id].rh == rh)
{
segTree[id].inc += val;
segTree[id].sm += val*(rh-lf+1);
return val*(rh-lf+1);
}
int mid = (segTree[id].lf + segTree[id].rh) / 2;
LL sum;
if (rh <= mid)
sum = update(id<<1, lf, rh, val);
else if (mid < lf)
sum = update((id<<1)|1, lf, rh, val);
else
sum = update(id<<1, lf, mid, val) + update((id<<1)|1, mid+1, rh, val);
segTree[id].sm += sum;
return sum;
}
LL query(int id, int lf, int rh)
{
if (rh < segTree[id].lf || segTree[id].rh < lf)
{
return 0;
}
if (inc = segTree[id].inc)
{ //查询的时候才更新子节点的增量
segTree[L(id)].inc += inc; //相当于对子区间进行一次update
segTree[L(id)].sm += inc * (segTree[L(id)].rh - segTree[L(id)].lf + 1);
segTree[R(id)].inc += inc;
segTree[R(id)].sm += inc * (segTree[R(id)].rh - segTree[R(id)].lf + 1);
segTree[id].inc = 0; //增量都传递到子区间去了,这里就要置零
}
if (lf == segTree[id].lf && rh == segTree[id].rh)
return segTree[id].sm;
int mid = (segTree[id].lf + segTree[id].rh) / 2;
if (rh <= mid)
return query(id<<1, lf, rh);
else if (mid < lf)
return query((id<<1)|1, lf, rh);
return query(id<<1, lf, mid) + query((id<<1)|1, mid+1, rh);
}
int main()
{
int i, j, x, y, v;
LL res;
char c;
while (scanf("%d%d", &n, &q) != EOF)
{
build(1, 1, n);
for (i = 1; i <= n; ++i)
{
scanf("%d", &j);
update(1, i, i, j);
}
while (q--)
{
getchar();
scanf("%c", &c);
scanf("%d %d", &x, &y);
if ('Q' == c)
{
res = query(1, x, y);
printf ("%I64d\n", res);
}
else
{
scanf("%d", &v);
update(1, x, y, v);
}
}
}
return 0;
}